# DERO Blockchain โ€” Full Documentation Corpus > Every documentation page for derod.org, inlined as Markdown for long-context LLM ingestion. Curated link list: https://derod.org/llms.txt. Each page is also available individually at https://derod.org/.md. --- --- title: "Understanding DERO: A Privacy-Focused Decentralized Application Platform | DERO Blockchain" description: "Explore DERO, a revolutionary privacy-focused blockchain platform with homomorphic encryption, private smart contracts, and robust security features." keywords: "DERO, blockchain privacy, decentralized applications, homomorphic encryption, private smart contracts, DVM, cryptocurrency, web3" date: "2024-08-26" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/dero_hero.jpeg" slug: "about-dero" canonicalUrl: "https://derod.org/basics/about" tags: ["dero", "blockchain", "privacy", "overview"] --- # What is DERO? ![What is DERO?](/assets/dero_hero.jpeg) ## The First Blockchain with Private Smart Contracts DERO combines **Bitcoin's security model** with **Ethereum's smart contracts** and **class-leading privacy** - all written from scratch in high-performance Golang. **What makes DERO unique:** - ๐Ÿ”’ **Private by Default** - All balances encrypted (homomorphic encryption) - โšก **Instant Confirmation** - Same-block finality (18 seconds) - ๐ŸŽฏ **Private Smart Contracts** - Full Turing-complete DVM with encrypted state - ๐Ÿ” **Ring Signatures** - Transaction anonymity (2-128 ring size) - ๐ŸŒ **TLS P2P Network** - Encrypted peer-to-peer communication ## Privacy-Preserving Features - [Homomorphic Encryption](/privacy/homomorphic-encryption.md) - [Private Smart Contracts](/features/smart-contracts.md) - [Turing Complete DVM](/features/dvm.md) - [Encrypted Network](/features/encrypted-network.md) - [PoW Mining](/basics/mining.md) - [Lightweight Wallet](/basics/wallets.md) ## Technical Specifications - Layer 1 Private Decentralized Application Platform - Fully Encrypted Blockchain - Fully Auditable Supply - 18 Second Blocktime - Same block/instant confirmation - No Soft Forks/Chain Splits - SSL/TLS UDP P2P Network - No Orphan Blocks - Homomorphic Encryption Protocol - Native dApp Support - Written from Scratch in Golang - 1.25 MB Block Size ## Cryptography & Consensus | Technology | Purpose | Why It Matters | |------------|---------|----------------| | **Bulletproofs** | Zero-knowledge range proofs | Proves amounts without revealing them | | **AstroBWT** | Mining algorithm (CPU-optimized) | Fair distribution, ASIC-resistant | | **Homomorphic Encryption** | Encrypted balance operations | Add/subtract without decryption | | **Ring Signatures** | Transaction anonymity | Hide sender among ring_size/2 potential senders (rings split evenly between senders and recipients) | | **ฮฃ-blocks (Sigma)** | Fast consensus | 1-second miniblocks, 18-second settlement | **Source:** `cryptography/crypto/` - Cryptographic implementations ## Tokenomics (Bitcoin Model) | Metric | Value | Notes | |--------|-------|-------| | **Ticker** | DERO | Native currency | | **Max Supply** | 21 Million | Same as Bitcoin | | **Mining Algorithm** | AstroBWT | CPU-optimized, ASIC-resistant | | **Block Time** | 18 seconds | vs Bitcoin's 10 minutes | | **Block Reward** | ~0.615 DERO | Halving every 4 years | | **Atomic Units** | 5 decimals | 1 DERO = 100,000 atomic units | | **Difficulty Adjustment** | Every block | Fast adaptation | **Emission:** Bitcoin-style halving schedule ensures predictable, deflationary supply. ## How DERO Compares | Feature | DERO | Other Privacy Coins | Ethereum | Bitcoin | |---------|------|---------------------|----------|---------| | **Privacy** | โœ… Default | โœ… Default | โŒ Public | โŒ Public | | **Smart Contracts** | โœ… Private | โŒ No | โœ… Public | โŒ No | | **Encrypted Balances** | โœ… Yes | โŒ No | โŒ No | โŒ No | | **Block Time** | โšก 18s | ๐Ÿข 2+ min | โšก 12s | ๐Ÿข 10 min | | **Language** | Golang | C++ | Various | C++ | | **ASIC Resistance** | โœ… Yes | โœ… Varies | N/A (PoS) | โŒ No | **DERO's Unique Position:** The only blockchain combining privacy-by-default with private smart contracts --- ## Why DERO Matters **For Users:** - Private transactions (no one can see your balance) - Fast confirmations (18 seconds vs Bitcoin's 10 minutes) - Private dApps (interact without revealing identity) **For Developers:** - Build private DeFi, games, DAOs with DVM-BASIC - Homomorphic encryption (balances stay encrypted on-chain) - No gas fees in Ethereum's sense (predictable costs) **For Miners:** - CPU mining (fair distribution, no ASICs) - ฮฃ-blocks (earn rewards every second) - Integrator rewards (10% of blocks on your public node) --- ## DERO in Production **Live Since:** 2017 (8+ years) **Mainnet:** Stargate (current version) **Development:** Active, open-source **Community:** Discord, GitHub, Reddit **Built for:** Privacy-focused applications, private DeFi, anonymous gaming, secure messaging, confidential business logic --- ## Related Pages **Get Started:** - [DERO Wallets](/basics/wallets.md) - Choose a wallet - [DERO Mining](/basics/mining.md) - Start mining - [Running a Node](/basics/running-a-node.md) - Run your own node **Core Features:** - [Privacy Suite](/privacy/index.md) - Complete privacy overview - [DERO Tokens](/basics/tokens.md) - Private assets - [Smart Contracts](/dvm/dero-virtual-machine.md) - DVM architecture **Technical Details:** - [Homomorphic Encryption](/privacy/homomorphic-encryption.md) - Encrypted balances - [Ring Signatures](/privacy/ring-signatures.md) - Transaction anonymity - [Golang Performance](/features/golang.md) - Why DERO is fast **Build on DERO:** - [DVM-BASIC Guide](/dvm/dvm-basic.md) - Smart contract programming - [Token Contract Tutorial](/smartContracts/token.md) - Build a token --- --- title: "DERO Daemon: Backbone of the Privacy Blockchain | DERO Blockchain" description: "Run a DERO node to support the network, earn integrator rewards, and maintain decentralization with full privacy features." keywords: ["DERO daemon", "blockchain node", "DERO network", "P2P service", "blockchain security", "privacy node", "decentralized network", "integrator rewards"] date: "2024-08-26" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/daemon.jpeg" slug: "daemon" canonicalUrl: "https://derod.org/basics/daemon" tags: ["basics", "daemon", "node", "P2P", "infrastructure"] --- # DERO Daemon (Node) ![DERO Daemon](/assets/daemon.jpeg) The DERO daemon (`derod`) is the core software that runs the DERO blockchain network. It validates transactions, maintains the blockchain, and connects peers in a decentralized P2P network. > [!NOTE] > **Download:** [GitHub Releases](https://github.com/deroproject/derohe/releases) --- ## What Does a Daemon Do? ```mermaid graph TB D[DERO Daemon] D --> V[Validate Transactions] D --> B[Store Blockchain] D --> P[P2P Network] D --> M[Mining Support] D --> R[RPC API] V --> BC[Blockchain State] B --> BC P --> BC M --> BC R --> BC ``` | Function | What It Does | Source Code | |----------|-------------|-------------| | **Transaction Validation** | Verify proofs, ring sigs, bulletproofs | `blockchain/transaction_verify.go` | | **Block Processing** | Execute transactions, update balances | `blockchain/transaction_execute.go:239` | | **P2P Networking** | Sync with peers, propagate blocks/TXs | `p2p/connection.go` | | **Mining** | Provide PoW templates, validate solutions | `blockchain/mining.go` | | **RPC API** | Serve wallet requests, smart contract calls | `rpc/rpc_dero.go` | --- ## Network Ports ### Mainnet | Service | Port | Purpose | |---------|------|---------| | **P2P** | 10101 | Node-to-node communication โ€” **randomized at startup**; pin with `--p2p-bind=0.0.0.0:10101` ([details](/basics/running-a-node.md#firewall-configuration)) | | **RPC** | 10102 | Daemon RPC API | | **Wallet RPC** | 10103 | Wallet communication | ### Testnet | Service | Port | Purpose | |---------|------|---------| | **P2P** | 40401 | Node-to-node communication (randomized; pin with `--p2p-bind=0.0.0.0:40401`) | | **RPC** | 40402 | Daemon RPC API | | **Wallet RPC** | 40403 | Wallet communication | **Source:** `config/config.go` (RPC + GETWORK ports); `p2p/controller.go:502` (P2P default `0.0.0.0:0` โ€” random); `README.md:133` (10101 convention). --- ## Verify your binaries Before running `derod` or `dero-wallet-cli` from a download, confirm the binary matches Captain's published GPG signature and the release sha512sum: ```bash gpg --verify checksum.txt.asc sha512sum dero_linux_amd64.tar.gz ``` Please every-time verify checksum of DERO binaries/source after downloading from github. Full instructions for installing Captain's GPG key and running the verification end-to-end are in the [DERO forum thread](https://forum.dero.io/t/verify-dero-code-and-binaries-release/2230). --- ## Reading the derod prompt When you start `derod`, the top of the terminal looks like this:
Details about DERO daemon prompt. Also run status/syncinfo/help cmd in daemon for details.
Every field on the prompt is a live signal. Once you can read it, you can diagnose almost any daemon problem at a glance. | # | Field on prompt | Meaning | |---|---|---| | 1 | `146658/146658` | **Local sync height** โ€” your node's chain tip | | 2 | `[146658/146658]` | **Network height** โ€” what your peers agree on | | 3 | `P 17` | **Peers** โ€” daemons currently connected to you | | 4 | `TXp 0` | **TX pool** โ€” transactions waiting to be included | | 5 | `0` | **Registration pool** โ€” wallet registrations waiting | | 6 | `NW 4.200 GH/s` | **Global network hashrate** | | 7 | `>Miners 1` | **Miners** connected to your daemon | | 8 | `98` | **Miniblocks** currently active in this machine's RAM | | 9 | `0s\|0s` | **Time offsets** โ€” NTP vs peer-derived | | 10 | `2ms>>` | **Latency** between this daemon and its peers | Read the prompt left to right: - When **1** and **2** match, you're synced. - When **9** shows non-zero seconds, your clock is drifting โ€” fix NTP (see [Mining โ†’ Time sync โ€” install chrony](/basics/mining.md#time-sync--install-chrony)). - When **10** climbs into the hundreds of ms, check your network. Three commands give you more detail any time you need it: ```bash status # chain height, peers, version, top hash syncinfo # per-peer height and direction help # full command list ``` ### MB / MBR / IB counters When you're mining (or operating a daemon other miners connect to), three additional counters appear under the prompt's Mining Stats: | Code | Meaning | Healthy? | |---|---|---| | `MB` | Miniblock submitted | yes | | `MBR` | Miniblock rejected (usually invalid PoW) | only if rare | | `IB` | Integrator block submitted | yes | MB-> Minblock submitted. MBR: Miniblock rejected due to invalidPOW or so. IB-> Integrator Block submitted. The `status` command's `Block Minted` line is `(MB + IB) โˆ’ MBR` โ€” so when `MBR` climbs, your minted count visibly drops. `MBR` is PoW-test rejection only (`cmd/derod/rpc/websocket_getwork_server.go:137`), so the root-causes to check, in order: (1) clock drift on the miner host ([Mining โ†’ Time sync](/basics/mining.md#time-sync--install-chrony)); (2) network instability dropping work mid-flight; (3) an unofficial miner binary submitting malformed work โ€” switch back to the official `dero-miner`. --- ## Running Your Own Node **Basic command:** ```bash ./derod-linux-amd64 # With custom settings ./derod-linux-amd64 --rpc-bind=0.0.0.0:10102 --p2p-bind=0.0.0.0:10101 ``` **System Requirements:** - **CPU:** 2 to 4 cores minimum - **RAM:** 4GB minimum - **Disk:** 15GB+ SSD (grows over time) - **Network:** Stable internet connection --- ## Integrator Rewards ### The 10% Daemon Bonus **How it works:** ``` Every 10 miniblocks โ†’ 1 integrator block โ€ข 9 regular miniblocks (normal difficulty) โ€ข 1 integrator block (9ร— difficulty) Integrator block reward โ†’ Your daemon address Result: Daemon operators earn ~10% of blocks mined on their node ``` **Why run your own daemon:** - โœ… Earn 10% integrator rewards (vs 1.6% fee to pool operators) - โœ… Support network decentralization - โœ… Full privacy (no third-party node) - โœ… Contribute to blockchain security **Source:** Miniblock system described in `blockchain/blockchain.go` --- ## Sync Status **Understanding the numbers:** ```bash # Daemon display Height: 6090778/6090778 โ† Synced! ^local ^network Not synced: 5500000/6090778 Syncing: 6090000/6090778 (99.9%) Synced: 6090778/6090778 โœ“ ``` **Fast sync vs Full sync:** - **Full sync:** Downloads and validates entire blockchain (slow, complete) - **Fast sync:** Downloads state snapshots (faster, still secure) ### Pruned-node height โ€” why your status looks short If you started your node with `--fastsync`, `status` will print a line like: ``` Chain is pruned till 6087500 ``` โ€ฆmeaning blocks before that point exist only on full-history nodes. The chain still validates correctly โ€” you just can't serve TX queries from before the prune point. Pls run `status` cmd in daemon & see what is your pruned node height. TXs before pruned height will not appear. If you need full history (e.g. to serve TX queries from genesis), there is no "backfill" โ€” `--fastsync` is a bootstrap-only flag (`cmd/derod/main.go:73`), and toggling it off post-bootstrap doesn't recover pruned blocks. Captain's recommended path for full history is to start over: stop `derod`, delete the `mainnet/` folder, and run a full sync from zero (no `--fastsync`). Don't use --fastsync. Sync full node. ### When your node gets stuck โ€” the pop escalation If your daemon stops advancing or believes a wrong tip, Captain's recommended recovery is to rewind blocks from the top and let the chain re-sync from your peers. pop 20 or 50000 blocks & see if you can start sync again. if not delete mainnet folder & start fullsync again, It takes 1 -2 days to do full sync on recent cpus with SSD. Sync may appear very slow for few hrs for some duration but it will sync very fast after that. In practice the ladder operators converge on is: | Step | Command | When | |---|---|---| | 1 | `pop 20` (in derod) | Brief hiccup, recent fork | | 2 | `pop 50000` | After step 1 doesn't unstick within minutes | | 3 | Stop `derod` โ†’ delete the `mainnet/` folder โ†’ restart with `--fastsync` | Nuclear option | Steps 1 and 2 are Captain's direct recommendation. Intermediate values (`pop 1000`, `pop 10000`) work the same way โ€” `pop N` simply rewinds `N` blocks; pick whatever distance reflects how far back you suspect the wedge is. --- ## Daemon as Mining Pool Each daemon acts as its own mining pool: | Role | Fee | How It Works | |------|-----|--------------| | **Daemon Operator** | 1.6% | Runs node, provides infrastructure | | **Miners** | 88.4% | Connect and mine, split proportionally | | **Integrator** | 10% | Daemon's address for integrator blocks | **Total:** 100% (nothing wasted) **Connect miners to your daemon:** ```bash # Miner connects to daemon ./dero-miner-linux-amd64 --daemon-rpc-address=127.0.0.1:10100 --wallet-address=dero1qy... ``` **Daemon tracks shares and distributes rewards automatically** **Source:** Mining pool logic in `blockchain/miniblocks.go` --- ## Key Features ### Privacy-Preserving - โœ… TLS-encrypted P2P connections - โœ… Stores encrypted balances (ElGamal) - โœ… Validates without revealing amounts - โœ… No metadata leakage ### Lightweight Storage ``` Blockchain storage: โ€ข Account: 66 bytes (encrypted balance) โ€ข Total accounts: Scales efficiently โ€ข Pruning: Can reduce disk usage 1 billion accounts = ~200GB (with overhead) Source: README.md (lines 92-98) ``` ### Fast Validation - Block time: ~18 seconds - Transaction verification: under 25ms - Instant balance queries: 66 bytes --- ## Daemon Commands **Interactive mode:** ```bash $ ./derod Commands available: status # Show blockchain height, peers peer_list # Connected peers diff # Current difficulty print_bc # Print blockchain info print_block # Show specific block print_tx # Show transaction details exit # Stop daemon ``` **Useful RPC calls:** ```bash # Get blockchain info curl http://127.0.0.1:10102/json_rpc \ -d '{"method":"DERO.GetInfo"}' # Get block details curl http://127.0.0.1:10102/json_rpc \ -d '{"method":"DERO.GetBlock","params":{"height":100000}}' ``` --- ## Why Run a Daemon? **Benefits:** | Benefit | Description | |---------|-------------| | **Privacy** | No third-party sees your queries | | **Integrator Rewards** | Earn 10% of blocks mined on your node | | **Network Support** | Contribute to decentralization | | **Self-Sovereignty** | Complete control, no trust needed | | **Mining Pool** | Support friends/family mining | **Trade-offs:** - Requires: Always-on machine, disk space, bandwidth - Maintains: Full blockchain copy - Syncs: Initially time-consuming --- ## Related Pages **Get Started:** - [Running a Node](/basics/running-a-node.md) - Complete VPS setup guide - [DERO Mining](/basics/mining.md) - How to mine with your node **API & Integration:** - [Daemon RPC API](/rpc-api/daemon-rpc-api.md) - Full API reference - [Network Ports & Setup](/features/encrypted-network.md) - P2P network details **Understanding DERO:** - [DERO Blockchain](/basics/about.md) - How DERO works - [Smart Contracts](/dvm/dero-virtual-machine.md) - DVM integration --- --- title: "DERO Mining: ฮฃ-blocks & Fair Rewards | DERO Blockchain" description: "Mine DERO with the revolutionary ฮฃ-blocks system. Solo mining made practical with daily rewards for everyone, from 100 KH/s hobbyists to data centers." keywords: ["DERO mining", "ฮฃ-blocks", "Sigma blocks", "solo mining", "AstroBWT", "CPU mining", "fair mining", "decentralized mining", "mining rewards"] date: "2024-08-26" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/mining.jpeg" slug: "mining" canonicalUrl: "https://derod.org/basics/mining" tags: ["basics", "mining", "ฮฃ-blocks", "AstroBWT", "rewards"] --- # DERO Mining ![DERO Mining](/assets/mining.jpeg) DERO's **ฮฃ-blocks** (also called *Sigma blocks*, *Sigma Mining* in older Captain posts, or `MiniBlock` in the source tree) turn the entire network into one giant mining pool. Even miners with 100 KH/s get daily rewards based on their hashrate contribution. > [!NOTE] > **Solo Mining Made Easy:** No pools needed - the network automatically distributes rewards proportionally to all miners every few minutes. --- ## The ฮฃ-Blocks Revolution **Traditional mining:** ``` Big miner (1 MH/s): Finds blocks โ†’ Gets rewards โœ“ Small miner (10 KH/s): Never finds blocks โ†’ Earns nothing โŒ Solution: Join pool, pay 2-5% fees Problem: Centralization, trust pools ``` **DERO ฮฃ-mining:** ``` Big miner (1 MH/s): 1000 shares/day โ†’ Proportional rewards โœ“ Small miner (10 KH/s): 10 shares/day โ†’ Proportional rewards โœ“ Solution: Network IS the pool Benefit: Everyone earns daily, no pools needed ``` --- ## How It Works ```mermaid graph LR M[Miners
Submit Work] --> SB[Miniblock
Every ~2 sec] SB --> MB[Main Block
Every 18 sec] MB --> SET[Settlement
~10 miniblocks] SET --> RWD[Distribute
Rewards] RWD --> MIN[All Miners
Get Paid] ``` | Metric | Value | Notes | |--------|-------|-------| | **Miniblock time** | ~1-2 seconds | ฮฃ-block (miniblock) emission | | **Main block** | 18 seconds | Settles 10 miniblocks | | **Settlement** | Every block | ~18 seconds | | **Daily miniblocks** | ~48,000 | 4,800 blocks ร— 10 miniblocks | | **Blocks per day** | ~4,800 | 86,400 seconds รท 18 | --- ## Reward Calculator **Your hashrate vs network determines reward frequency:** | Your Share of Network | Reward Frequency | Example Hashrate* | |----------------------|------------------|------------------| | 1/48,000 | Daily | 1 KH/s (if network = 48 MH/s) | | 1/96,000 | Every 2 days | 500 H/s (if network = 48 MH/s) | | 1/480,000 | Every 10 days | 100 H/s (if network = 48 MH/s) | *Network hashrate varies - check current hashrate in your daemon/miner output **Formula:** ``` Your expected miniblocks per day = (Your hashrate / Network hashrate) ร— 48,000 Example: You: 10 KH/s Network: 48 MH/s Your share: 10,000 / 48,000,000 = 0.0208% Daily miniblocks: 48,000 ร— 0.0208% = 10 miniblocks/day ``` --- ## Mining Algorithm ### AstroBWT v3 **CPU-optimized, ASIC-resistant:** ``` Memory requirement: ~256MB per thread Difficulty: Adjusts every block Target block time: 18 seconds ``` **Why CPU-only?** - โœ… Democratizes mining (everyone has CPU) - โœ… Prevents ASIC dominance - โœ… Lower barrier to entry - โœ… Better decentralization **Source:** `astrobwt/` directory, `pow/pow.go` --- ## Solo Mining Setup **Step 1: Run Daemon** ```bash ./derod-linux-amd64 --integrator-address=dero1qy...your_address ``` **Step 2: Start Miner** ```bash ./dero-miner-linux-amd64 \ --daemon-rpc-address=127.0.0.1:10100 \ --wallet-address=dero1qy...your_address \ --mining-threads=4 ``` **Step 3: Monitor** ``` Miner output: Hashrate: 10.5 KH/s Shares: 150 submitted Blocks: 2 found today Daemon output: Miniblocks: Being processed Height: Increasing Wallet: Rewards: Arriving proportionally based on your miniblock contributions ``` ### Time sync โ€” install chrony Miniblocks carry timestamps. `derod`'s peer time check rejects clock offsets over **ยฑ1 second** (`p2p/timecheck.go:86`) โ€” sustained drift breaks chain sync and your blocks can be rejected by peers. `MBR` is a separate counter that tracks PoW-test failures only (`cmd/derod/rpc/websocket_getwork_server.go:137` โ€” *"only counting rejected as those which didnot pass Pow test"*), so clock drift won't show up there directly โ€” it'll surface as failed peer time syncs and lost miniblocks. Captain's recommendation is **chrony**, not the default `ntpd`: Install chrony much better than ntp. **Install:** ```bash # Debian / Ubuntu sudo apt install chrony # CentOS / RHEL / Fedora sudo yum install chrony # Start and enable sudo systemctl enable --now chrony ``` **Captain's recommended config** โ€” add to `/etc/chrony.conf` or `/etc/chrony/chrony.conf`: ``` server time.google.com iburst prefer server time.cloudflare.com iburst prefer ``` Add in /etc/chrony.conf or /etc/chrony/chrony.conf following:
`server time.google.com iburst prefer`
`server time.cloudflare.com iburst prefer` **Verify:** ```bash chronyc tracking # confirm offset is in microseconds, not seconds ``` If your `derod` prompt shows non-zero values in field 9 (time offsets โ€” `Bs|Cs|Dms`), your clock is the problem โ€” fix chrony first. --- ## Reward Breakdown **Every ฮฃ-block reward distributed as:** | Recipient | Percentage | Goes To | |-----------|-----------|---------| | **Miners** | 88.4% | Split among share contributors | | **Integrator** | 10% | Daemon operator's address | | **Pool Fee** | 1.6% | Daemon operator (your daemon = you keep this!) | **If mining on your own daemon:** - You get: 88.4% (miner share) + 10% (integrator) + 1.6% (fee) = **100%** - Pool miners get: 88.4% only **Advantage:** 11.6% more rewards by running your own node! --- ## Mining Performance ### Hashrate Expectations **CPU Performance (approximate):** | CPU | Threads | Expected Hashrate | |-----|---------|------------------| | Intel i5 (modern) | 4 | 5-8 KH/s | | Intel i7 (modern) | 8 | 10-15 KH/s | | AMD Ryzen 5 | 6 | 8-12 KH/s | | AMD Ryzen 9 | 16 | 20-30 KH/s | | Server (high-end) | 32+ | 50-100+ KH/s | **Benchmark your hardware:** ```bash ./dero-miner --bench ``` This runs local performance tests and shows hashrate for different thread counts. --- ## Mining Pools vs Solo | Aspect | Traditional Pool | DERO Solo (ฮฃ-blocks) | |--------|-----------------|---------------------| | **Rewards** | Daily, but 2-5% fee | Daily, 0% fee (own node) | | **Setup** | Easy (just connect) | Medium (run daemon) | | **Centralization** | High (pool controls) | Low (you control) | | **Trust** | Trust pool operator | Trustless | | **Small miner friendly** | โœ… Yes | โœ… Yes (even better!) | **DERO = Best of both worlds** ### Captain's doctrine โ€” solo on your own node This isn't editorial framing. It's the architect's direct recommendation, repeated across the post-Stargate window: DERO doesn't require pools to mine. Solo mining is recommended on DERO network. Just run your own node & mine on local node. No need to pay any fees to anyone. Solo mining to your own node is preferred way for your privacy & security of DERO network. Captain also shared specific reasoning during the same period: a single daemon supports more than 10,000 miners ([2022-11-17, #suggestions](https://discord.com/channels/419781880632836096/557277155436789760/1042706857195733024)), and bench tests show solo mining has same-or-better rewards than pool ([2023-04-04, #dero-mining](https://discord.com/channels/419781880632836096/427613001537814540/1092655070623039498)). Sigma Mining's miniblock structure means even small miners produce shares regularly โ€” the long variance penalty that drives pool culture on Bitcoin doesn't apply here the same way. A single daemon supports 10,000+ connected miners, so even a family or small mining group can share one node without scaling concerns. --- ## Getting Started **Quick start:** 1. **Download:** ```bash https://github.com/deroproject/derohe/releases ``` 2. **Run daemon:** ```bash ./derod --integrator-address=YOUR_ADDRESS ``` 3. **Mine:** ```bash ./dero-miner --daemon-rpc-address=127.0.0.1:10100 --wallet-address=YOUR_ADDRESS ``` 4. **Profit:** ``` Start contributing miniblock shares immediately Rewards arrive proportional to your hashrate contribution Check wallet for incoming miniblock rewards ``` --- ## Optimizing Mining **CPU Settings:** ```bash # Use all cores except 1 (keep system responsive) --mining-threads=$(nproc --ignore=1) # Set process priority nice -n 19 ./dero-miner ... ``` **Multiple Machines:** ```bash # All point to your daemon Machine 1: ./dero-miner --daemon-rpc-address=192.168.1.100:10100 Machine 2: ./dero-miner --daemon-rpc-address=192.168.1.100:10100 Machine 3: ./dero-miner --daemon-rpc-address=192.168.1.100:10100 # Daemon tracks all shares, distributes rewards ``` --- ## Mining Economics **Block reward:** Currently ~0.615 DERO per block (decreases over time via halving) **Daily emission:** ``` Blocks per day: ~4,800 (86,400 seconds / 18 seconds) Daily emission: ~2,952 DERO ``` **Your daily earnings (example):** ``` Your hashrate: 10 KH/s Network: 48 MH/s Your share: 10,000 / 48,000,000 = 0.0208% Daily rewards: 4,800 ร— 0.0208% = ~1 DERO/day Miniblock rewards: 48,000 ร— 0.0208% = ~10 miniblocks/day ``` *Values are approximate and change with network hashrate and block rewards* --- ## Common Questions **Q: Can I mine with GPU/ASIC?** A: No - AstroBWT is memory-hard, CPU-optimized. GPUs/ASICs have no advantage. **Q: Do I need a pool?** A: No - ฮฃ-blocks make solo mining practical for everyone. **Q: How often do I get paid?** A: Miniblocks settle every 18 seconds (each main block). You receive rewards proportional to your contributed shares in each block. **Q: What if my hashrate is tiny?** A: You'll still get rewards proportional to your hashrate share! Even 100 H/s contributes to miniblocks and earns rewards, just less frequently than higher hashrates. --- ## Key Takeaways **What makes DERO mining special:** - โœ… **ฮฃ-blocks** - Network is one giant pool - โœ… **Solo mining works** - Even for small miners - โœ… **Daily rewards** - Proportional to hashrate - โœ… **No pools needed** - Decentralized by design - โœ… **CPU-only** - Fair, accessible to all - โœ… **Integrator rewards** - 10% bonus for node operators > [!NOTE] > **Start small, earn daily:** Even a laptop can mine DERO profitably. Try it with 1-2 threads and see rewards within hours! --- ## Related Pages **Get Started Mining:** - [Run a Daemon](/basics/daemon.md) - Setup your own node - [Running a Node](/basics/running-a-node.md) - VPS integrator node guide - [DERO Wallets](/basics/wallets.md) - Store your mining rewards **Technical Details:** - [AstroBWT Algorithm](/features/astroBWT.md) - Mining algorithm explained - [Golang Performance](/features/golang.md) - Why DERO is fast **Resources:** - [Mining Pools Stats](https://miningpoolstats.stream/dero) - Available mining pools - [Daemon RPC API](/rpc-api/daemon-rpc-api.md) - Get block templates for mining - [DERO Discord](https://discord.gg/H95TJDp) - Mining help and community --- --- title: "Running a DERO Node: Complete Setup Guide | DERO Blockchain" description: "Step-by-step guide to setting up and running your own DERO node on Linux, Windows, or Mac. Earn integrator rewards and support network decentralization." keywords: ["DERO node setup", "run DERO daemon", "blockchain node", "DERO installation", "node configuration", "integrator rewards", "DERO network", "decentralization"] date: "2025-10-19" lastUpdated: "2026-05-29" authors: ["DHEBP"] image: "/assets/daemon.jpeg" slug: "running-a-node" canonicalUrl: "https://derod.org/basics/running-a-node" tags: ["basics", "node", "daemon", "setup", "configuration"] --- # Running Your Own DERO Node ![Run a DERO Node](/assets/dero_node.png) Running a DERO node supports network decentralization, earns you integrator rewards (10% bonus), and gives you complete privacy without relying on third-party infrastructure. > [!NOTE] > **Download:** [GitHub Releases](https://github.com/deroproject/derohe/releases) --- ## Quick Start ### Linux ```bash # Download latest release wget https://github.com/deroproject/derohe/releases/latest/download/dero-linux-amd64.tar.gz # Extract tar -xzf dero-linux-amd64.tar.gz cd dero-linux-amd64 # Run daemon ./derod-linux-amd64 --integrator-address=YOUR_DERO_ADDRESS ``` ### Windows ```powershell # Download from GitHub releases # Extract ZIP file # Open PowerShell in extracted folder .\derod-windows-amd64.exe --integrator-address=YOUR_DERO_ADDRESS ``` ### macOS ```bash # Download for your architecture (Intel or Apple Silicon) # Extract archive cd dero-darwin-* # Run daemon ./derod-darwin-amd64 --integrator-address=YOUR_DERO_ADDRESS ``` --- ## System Requirements | Component | Minimum | Recommended | |-----------|---------|-------------| | **CPU** | 2 cores | 4+ cores | | **RAM** | 4GB | 8GB+ | | **Storage** | see note below | see note below | | **Network** | Stable connection | 100+ Mbps | | **OS** | Linux/Windows/Mac | Linux (best performance) | **Storage depends on your sync mode** โ€” this is the number that catches people out: | Sync mode | Disk | Use when | |-----------|------|----------| | **Full / archival** (default `derod`, no pruning) | **~230 GB+ today; plan for 500 GB** (grows continuously) | you need complete chain history and to answer queries about any past block or transaction | | **Fast sync + pruning** (`--fastsync --prune-history=100000`) | **~50 GB** | typical node or VPS โ€” current state, recent history, validating new blocks | The full chain has grown from ~130 GB (early 2025) to 160+ GB (late 2025) and past 230 GB by mid-2026, and it keeps climbing โ€” size a full node for the future, not for today. A pruned, fast-synced node stays light and is the recommended setup for a VPS or any node that does not need deep history. **Why SSD?** - Blockchain requires fast random reads/writes - HDD will cause sync issues and slow performance --- ## Configuration ### Basic Setup ```bash # Minimal configuration ./derod-linux-amd64 --integrator-address=dero1qy... # With custom ports ./derod-linux-amd64 \ --integrator-address=dero1qy... \ --rpc-bind=0.0.0.0:10102 \ --p2p-bind=0.0.0.0:10101 ``` ### Advanced Configuration ```bash # Production node with optimizations ./derod-linux-amd64 \ --integrator-address=dero1qy... \ --rpc-bind=0.0.0.0:10102 \ --p2p-bind=0.0.0.0:10101 \ --node-tag="MyNode" \ --fastsync ``` **Key flags:** - `--integrator-address` - Your address for 10% rewards - `--rpc-bind` - RPC server address (default: 127.0.0.1:10102) - `--p2p-bind` - P2P network address (default: 0.0.0.0:10101) - `--node-tag` - Custom node identifier - `--fastsync` - Faster initial sync **Full list:** `./derod --help` --- ## Running as a Service ### Linux (systemd) First, create a dedicated user and directory for the daemon: ```bash sudo useradd -r -s /bin/false dero sudo mkdir -p /opt/dero sudo chown dero:dero /opt/dero # Copy derod binary to /opt/dero/ ``` Create service file `/etc/systemd/system/derod.service`: ```ini [Unit] Description=DERO Daemon After=network.target [Service] Type=simple User=dero WorkingDirectory=/opt/dero ExecStart=/opt/dero/derod-linux-amd64 --integrator-address=YOUR_ADDRESS Restart=always RestartSec=10 [Install] WantedBy=multi-user.target ``` **Enable and start:** ```bash sudo systemctl enable derod sudo systemctl start derod sudo systemctl status derod ``` **View logs:** ```bash journalctl -u derod -f ``` --- ## Monitoring Your Node ### Check Sync Status ```bash # In daemon console (if running interactively) status Output: Height: 7115506/7115506 โ† Synced! ^local ^network Peers: 16 Network: Mainnet ``` ### Via RPC ```bash # Get node info curl http://127.0.0.1:10102/json_rpc -d '{ "jsonrpc":"2.0", "id":"1", "method":"DERO.GetInfo" }' | jq # Returns: { "height": 7115506, "stableheight": 7115498, "topoheight": 7115506, "difficulty": 36457876, "network": "mainnet" } ``` ### Check Connected Peers ```bash curl http://127.0.0.1:10102/json_rpc -d '{ "jsonrpc":"2.0", "id":"1", "method":"DERO.GetPeerList" }' | jq ``` --- ## Firewall Configuration ### DERO ports (Stargate mainnet) | Service | Default Port | Notes | |---|---|---| | P2P | `10101` | **Randomized at startup** โ€” check `derod` log for actual port, or pin with `--p2p-bind=0.0.0.0:10101` | | RPC | `10102` | Daemon JSON-RPC | | Wallet RPC | `10103` | Wallet JSON-RPC | | GETWORK | `10100` | Miner connections (`dero-miner --daemon-rpc-address=127.0.0.1:10100`) | P2P Default Port: 10101 But Randomized, check daemon during startup for exact port used or use --p2p-bind=0.0.0.0:10102. > [!WARNING] > **Typo in Captain's example.** The `--p2p-bind=0.0.0.0:10102` above is verbatim from Discord โ€” `10102` is the **RPC** port (see the table). For P2P, pin `0.0.0.0:10101` to match the convention and the UFW example below. If you're behind NAT, **pin the P2P port** before opening firewall rules โ€” randomization will silently break port forwarding. **Mainnet (UFW example):** ```bash # P2P (pin the port first with --p2p-bind, then open the same port here) sudo ufw allow 10101/tcp # GETWORK (only if miners connect from outside the host) sudo ufw allow 10100/tcp # RPC (local access only โ€” never expose to the internet) sudo ufw allow from 127.0.0.1 to any port 10102 ``` **Testnet:** ```bash sudo ufw allow 40401/tcp ``` > [!WARNING] > **Security:** Do NOT expose RPC port (10102) to the internet unless you know what you're doing. It should only be accessible locally or via trusted network. --- ## Initial Sync ### Sync Methods **1. Full Sync โ€” complete history** ```bash ./derod-linux-amd64 # Downloads and validates the entire blockchain from genesis # Time: several hours (depends on connection/CPU) # Disk: full archival (~230 GB+, see System Requirements) # Result: fully validated node that can answer queries about any past block/tx ``` **2. Fast Sync โ€” recommended for most nodes** ```bash ./derod-linux-amd64 --fastsync # Downloads recent state snapshots instead of replaying from genesis # Time: 30-60 minutes # Result: functional, secure node. Pair with --prune-history to keep disk small. ``` Most operators want **fast sync + pruning** (see "For VPS/Server" under Performance Optimization). Choose full sync only if you specifically need the complete historical chain. ### Fastsync vs `--add-priority-node` โ€” what each flag does These two flags are commonly conflated. They solve different problems: | Flag | What it does | When to use | |---|---|---| | `--fastsync` | Skip historical block bodies during initial sync; download recent state snapshots instead. | One-time onboarding to get your node online quickly. **Bootstrap-only flag** โ€” it's a no-op after first sync, so you can leave it on or drop it; either way you'll keep validating new blocks normally. | | `--add-priority-node=ip:port` | Always keep this specific peer connected during sync. | When you want to bias the sync process toward a peer you trust (a friend's node, a foundation seed, etc.). | Fastsync is used to sync your node only. After your node is synced by normal/fastsync you can use it for mining. Priority node option is used to select node of your preference for sync process. You can use both at the same time โ€” fastsync to skip history, priority node to choose your seed. ### Monitoring Sync Progress ```bash # Check height increasing watch -n 5 'curl -s http://127.0.0.1:10102/json_rpc -d '\''{"method":"DERO.GetInfo"}'\'' | jq .result.height' # Synced when local height = network height ``` --- ## Maintenance ### Updating Your Node ```bash # Stop daemon pkill derod # Download latest release wget https://github.com/deroproject/derohe/releases/latest/download/dero-linux-amd64.tar.gz # Extract and replace tar -xzf dero-linux-amd64.tar.gz # Restart with same settings ./derod-linux-amd64 --integrator-address=YOUR_ADDRESS ``` ### Pruning (Reducing Disk Usage) ```bash # Start with pruning enabled ./derod-linux-amd64 --prune-history=100000 # Keeps last 100,000 blocks, prunes older # Reduces disk usage significantly # Node remains fully functional ``` **Source:** Pruning implementation in `blockchain/prune_history.go` --- ## Earning Integrator Rewards ### The 10% Bonus Explained **Every 10 miniblocks:** ``` Blocks 1-9: Regular (distributed to miners) Block 10: Integrator (goes to your daemon address) ``` **Requirements:** - Run your own daemon - Set `--integrator-address` to your wallet - Have miners connected (or mine yourself) **Rewards:** - Base miner rewards: 88.4% - Integrator bonus: 10% - Pool fee (you keep): 1.6% - **Total: 100%** (vs 98.4% on public pools) **Source:** `blockchain/miniblocks.go` --- ## Troubleshooting ### Common Issues **Sync stuck:** ```bash # Check peers curl http://127.0.0.1:10102/json_rpc -d '{"method":"DERO.GetPeerList"}' # If no peers, check firewall (port 10101) # Try adding seed nodes manually (usually not needed) ``` **High CPU usage:** ```bash # Use nice to lower priority nice -n 19 ./derod-linux-amd64 ``` **High memory:** ```bash # Enable low memory mode ./derod-linux-amd64 --prune-history=50000 ``` **Port already in use:** ```bash # Change ports ./derod-linux-amd64 --p2p-bind=0.0.0.0:20101 --rpc-bind=127.0.0.1:20102 ``` --- ## Performance Optimization ### For VPS/Server ```bash # Optimize for server environment ./derod-linux-amd64 \ --integrator-address=YOUR_ADDRESS \ --rpc-bind=0.0.0.0:10102 \ --p2p-bind=0.0.0.0:10101 \ --fastsync \ --prune-history=100000 ``` ### For Home PC ```bash # Optimize for home use (lower resource usage) ./derod-linux-amd64 \ --integrator-address=YOUR_ADDRESS \ --rpc-bind=127.0.0.1:10102 ``` --- ## Run your own block explorer You don't have to rely on `explorer.dero.io`. The `explorer` binary ships in the same release as `derod` and talks to your local daemon. ```bash ./explorer-linux-amd64 --daemon-address=127.0.0.1:10102 --http-address=0.0.0.0:8080 ``` Open `http://127.0.0.1:8080` in your browser. Personal explorer `./explorer-linux-amd64 --daemon-address=127.0.0.1:10102 --http-address=0.0.0.0:8080` Open in browser 127.0.0.1:8080 for your local explorer. Running a local explorer is the privacy-preserving default: public explorers see every query you make โ€” block lookups, address checks, TX inspections โ€” while the command Captain shared above runs against your own daemon, so nothing leaves the host. --- ## Seed nodes are bootstrap only DERO's seed nodes are not a control plane. They exist so a fresh node can find its first peers; after that, peer exchange takes over and the seed nodes can vanish without affecting your daemon. DERO seed nodes are not required except to bootstrap network. DERO is actual decentralized network & will remain so. DERO core devs will never be part of some centralized thing. There are so many other protocols & chains which can be freezed/halted/selective, feel free to join those networks. If you want to fully decouple from the default seed list, run `--add-priority-node=:10101` (see [Fastsync vs --add-priority-node](#fastsync-vs---add-priority-node--what-each-flag-does) above) and you never have to talk to a seed node again. --- ## `--remote` is convenience, not sovereignty The wallet CLI accepts a `--remote` flag that connects to a public DERO Foundation node instead of your own daemon: ```bash ./dero-wallet-cli-linux-amd64 --remote # Connects to node.derofoundation.org:11012 โ€” config/config.go:140-141 ``` It works โ€” and for read-only operations or quick balance checks it's fine. What you give up is the self-sovereignty premise of the rest of this page: with `--remote`, you're trusting one party's view of the chain. They could censor your transactions, lie about your balance, or correlate every query you make. For anything that matters โ€” large balances, smart-contract operations, payment processing, anything you'd describe as "real" โ€” point your wallet at your own daemon: ```bash ./dero-wallet-cli-linux-amd64 --daemon-address=127.0.0.1:10102 ``` This is the whole point of running a node. --- ## Security Best Practices **1. Firewall Rules** - โœ… Allow P2P port (10101) - โŒ Block RPC port from internet (10102) - โœ… Use SSH keys (if remote server) **2. System Security** - โœ… Keep OS updated - โœ… Run daemon as non-root user - โœ… Use strong passwords - โœ… Enable automatic security updates **3. Backup** - โœ… Backup wallet seed phrase (25 words) - โœ… Document integrator address - โœ… Note configuration settings > [!CAUTION] > **Never expose RPC port to the internet!** It can be used to query blockchain data and potentially DOS your node. Use SSH tunneling or VPN if remote access needed. --- ## Benefits of Running a Node | Benefit | Description | |---------|-------------| | **Privacy** | No third party sees your transactions/queries | | **Integrator Rewards** | Earn 10% of blocks mined on your node | | **Network Health** | Contribute to decentralization | | **Self-Sovereignty** | Complete control, zero trust | | **Support Mining** | Help friends/family mine | | **Learning** | Understand blockchain deeply | --- ## Further Reading - [DERO Daemon](/basics/daemon.md) - Understanding the daemon - [Mining Guide](/basics/mining.md) - Start mining on your node - [RPC API](/rpc-api/daemon-rpc-api.md) - API documentation **Source Code:** - Daemon implementation: `cmd/derod/main.go` - Configuration: `config/config.go` - Pruning: `blockchain/prune_history.go` --- ## Related Pages **Node Operations:** - [DERO Daemon](/basics/daemon.md) - Understanding the daemon - [DERO Mining](/basics/mining.md) - Mine with your node - [Encrypted Network](/features/encrypted-network.md) - P2P network details **APIs & Integration:** - [Daemon RPC API](/rpc-api/daemon-rpc-api.md) - Full RPC reference - [Wallet RPC API](/rpc-api/wallet-rpc-api.md) - Wallet automation **Advanced:** - [Smart Contracts](/dvm/dero-virtual-machine.md) - Run smart contracts on your node - [DERO Tokens](/basics/tokens.md) - Understanding asset storage --- --- title: "DERO Tokens: Private Smart Contract Assets | DERO Blockchain" description: "Learn about DERO's innovative approach to token storage and security, offering rugpull-resistant tokens with enhanced privacy features." keywords: ["DERO tokens", "private smart contracts", "fungible tokens", "non-fungible tokens", "secure cryptocurrency", "blockchain assets", "anonymous tokens", "privacy-focused tokens"] date: "2024-08-26" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/tokens.jpeg" slug: "tokens" canonicalUrl: "https://derod.org/basics/tokens" tags: ["basics", "tokens", "smart-contracts", "privacy", "NFT"] --- # DERO Tokens ![Tokens](/assets/tokens.jpeg) Tokens on DERO are user-created assets deployed through smart contracts. What makes DERO unique is that tokens are stored as **encrypted balances in user wallets**, not in the smart contract itself - providing privacy and rug-pull resistance. --- ## How DERO Tokens Are Different | Aspect | ERC-20 (Ethereum) | DERO Tokens | |--------|------------------|-------------| | **Storage** | In smart contract | In user wallets | | **Balance Privacy** | ๐Ÿ‘๏ธ Public | ๐Ÿ”’ Encrypted (66 bytes) | | **Transfers** | Through contract | Wallet-to-wallet (like DERO) | | **Contract Control** | Can freeze/lock | โŒ Cannot control after issuance | | **Rug-Pull Risk** | โš ๏ธ High | โœ… Resistant | | **Privacy** | โŒ None | โœ… Ring sigs + encryption | --- ## Token Storage Model ### Traditional Tokens (ERC-20) ```solidity // ALL balances in contract mapping(address => uint256) balances; balances[alice] = 1000; // Public, everyone sees balances[bob] = 500; // Public, everyone sees ``` **Problem:** Contract controls everything. Owner can freeze, steal, or manipulate. ### DERO Tokens ```basic // Tokens sent to WALLETS Function IssueAsset() Uint64 10 SEND_ASSET_TO_ADDRESS(SIGNER(), amount, SCID()) 20 RETURN 0 End Function ``` **Result in wallet:** ``` Alice's wallet contains: DERO: E(500) // Encrypted 500 DERO (66 bytes) Token: E(1000) // Encrypted 1000 tokens (66 bytes) Each encrypted balance stored as ElGamal: Left: 33 bytes Right: 33 bytes Total: 66 bytes per asset ``` **Source:** `cryptography/crypto/algebra_elgamal.go:91-93`, `cryptography/crypto/balance_serdes.go:31` --- ## Privacy Features **Token transfers use DERO's full privacy stack:** 1. **Ring Signatures** - Sender hidden among ring_size/2 potential senders (rings split evenly) 2. **Homomorphic Encryption** - Amounts encrypted 3. **Bulletproofs** - Zero-knowledge validation 4. **TLS Network** - Encrypted transmission **Verified in source:** - Balance storage: `blockchain/transaction_execute.go:239` - `nb.Balance.Add(echanges)` (homomorphic) - Token sending: `dvm/dvm_functions.go:80` - `SEND_ASSET_TO_ADDRESS` implementation - Wallet updates: `dvm/simulator.go:378` - `nb.Balance.Plus()` for tokens --- ## Rug-Pull Resistance ### Why DERO Tokens Are Safer **Ethereum ERC-20:** ```solidity // Contract owner can: function freeze(address user) onlyOwner { balances[user] = 0; // Steal tokens } function pause() onlyOwner { paused = true; // Lock all transfers } ``` **DERO Tokens:** ```basic // Once issued to wallet, contract CANNOT: // โŒ Freeze tokens // โŒ Take them back // โŒ See your balance // โŒ Control transfers // Tokens in YOUR wallet = YOU control them ``` **The "Cash Model":** - Bank (contract) issues cash (tokens) - Cash leaves bank โ†’ in your wallet (encrypted) - Bank can't track or control it anymore - You can spend it peer-to-peer ### Captain on the wallet-native model Captain summarized the same model in chat โ€” native assets, wallet-custodied, contract-independent: Yes, On DERO network assets/tokens etc. are native unlike ETH/other tokens. Assets/tokens once issued on DERO network are owned by DERO wallet NOT by issuing Smart Contract. Even if you update/delete/blacklist Smart Contract your assets won't be affected in any way on DERO NW & they will move freely as ever. The SC defines what an asset *is* (its SCID is the asset's identity); it does not custody the balances. --- ## Token Types ### Fungible Tokens **Example:** Stablecoins, utility tokens, governance tokens ```basic Function InitializePrivate() Uint64 10 STORE("total_supply", 1000000) 20 SEND_ASSET_TO_ADDRESS(SIGNER(), 1000000, SCID()) 30 RETURN 0 End Function ``` **Each token is identical and interchangeable** ### Non-Fungible Tokens (NFTs) **Example:** Collectibles, game items, unique assets ```basic Function MintNFT(recipient String, token_id Uint64) Uint64 10 SEND_ASSET_TO_ADDRESS(ADDRESS_RAW(recipient), 1, token_id) 20 RETURN 0 End Function ``` **Each token has unique ID, quantity = 1** --- ## Using DERO Tokens ### Receiving Tokens Tokens arrive in your wallet automatically via `SEND_ASSET_TO_ADDRESS()`: ``` Transaction received: SCID: 0abc123def... (token identifier) Amount: E(100) (encrypted 100 tokens) Your wallet now contains: E(previous_balance) + E(100) = E(new_balance) All done homomorphically - no decryption needed! ``` ### Sending Tokens Transfer like native DERO: ```bash # Using wallet RPC curl -X POST http://127.0.0.1:10103/json_rpc -d '{ "method": "transfer", "params": { "transfers": [{ "destination": "dero1qy...", "amount": 100, "scid": "token_scid_here" }], "ringsize": 16 } }' ``` **Privacy features:** - Ring signature hides sender - Amount encrypted - Balance stays encrypted --- ## Key Advantages **1. Wallet Storage = True Ownership** - โœ… You control private keys - โœ… Contract cannot take back - โœ… No freeze functions possible **2. Privacy = Full Encryption** - โœ… Balances encrypted (E(amount)) - โœ… Transfers use ring signatures - โœ… Cannot track ownership **3. Peer-to-Peer Transfers** - โœ… Send without contract involvement - โœ… Like sending DERO - โœ… Fast and private **4. Multiple Assets Per Wallet** - โœ… DERO + unlimited tokens - โœ… Each encrypted separately - โœ… All in one wallet --- ## Learn More - [Private Smart Contracts](/privacy/private-smart-contracts.md) - How token privacy works - [Homomorphic Encryption](/privacy/homomorphic-encryption.md) - Why balances stay encrypted - [DVM Smart Contracts](/dvm/dero-virtual-machine.md) - Building token contracts **Source Code References:** - Token implementation: `dvm/dvm_functions.go:398` - `SEND_ASSET_TO_ADDRESS` - Wallet storage: `cryptography/crypto/balance_serdes.go:31` - `Balance *ElGamal` - Homomorphic updates: `blockchain/transaction_execute.go:239` - `nb.Balance.Add(echanges)` --- ## Related Pages **Understand Token Privacy:** - [Homomorphic Encryption](/privacy/homomorphic-encryption.md) - How encrypted balances work - [Ring Signatures](/privacy/ring-signatures.md) - Transaction privacy layer - [Private Smart Contracts](/privacy/private-smart-contracts.md) - Token contract privacy **Build with Tokens:** - [Token Smart Contract](/smartContracts/token.md) - Full token implementation example - [Assets Exchange](/smartContracts/assets.md) - Build a token swap contract - [DVM-BASIC Guide](/dvm/dvm-basic.md) - Smart contract programming language **Deploy & Use:** - [Wallet RPC API](/rpc-api/wallet-rpc-api.md) - Send and receive tokens - [DERO Wallets](/basics/wallets.md) - Wallet options for managing tokens --- --- title: "DERO Cryptocurrency Wallets: A Comprehensive Guide | DERO Blockchain" description: "Explore DERO wallet options, including CLI, Engram, Web, and Cold wallets for secure cryptocurrency management with enhanced privacy." keywords: ["DERO wallets", "cryptocurrency security", "CLI wallet", "Engram wallet", "cold storage", "blockchain privacy", "secure crypto storage", "DERO ecosystem"] date: "2024-08-26" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/wallets.jpeg" slug: "wallets" canonicalUrl: "https://derod.org/basics/wallets" tags: ["basics", "wallets", "CLI", "Engram", "security"] --- # What is a wallet? ![What is a wallet](/assets/wallets.jpeg) A cryptocurrency wallet is a digital tool or software application that allows users to securely store, manage, and interact with their cryptocurrencies. It serves as a virtual wallet for storing private keys, which are essential for accessing and controlling the user's cryptocurrency holdings on the blockchain. Many cryptocurrency wallets, including Dero's, employ seed phrasesโ€”a sequence of random dictionary words. These seed phrases enable the regeneration of a lost private key, underscoring their crucial role in wallet security. It is strongly advised to diligently record and store your seed phrase. Dero adopts a 25-word seed phrase, displayed during wallet creation and accessible for printing at any time within the wallet interface. Download here: https://github.com/deroproject/derohe/releases ## Dero Wallet Options ### CLI (Command Line Interface) Wallet The CLI wallet, the fundamental and official wallet, resides [here](https://github.com/deroproject/derohe) within the official Dero suite of software. Offering all necessary functions, starting with this wallet is recommended. #### Usage: To utilize the CLI wallet, execute the binary file via the command line or terminal. The process might slightly differ based on your operating system. Nevertheless, navigate to the folder containing the executable and run it accordingly: - Linux: `./dero-wallet-cli-linux-amd64` - Windows: `dero-wallet-cli-windows-amd64.exe` - Mac (Intel): `./dero-wallet-cli-darwin-amd64` - Mac (Apple Silicon): `./dero-wallet-cli-darwin-arm64` ### ENGRAM (Graphical) Wallet Engram is DERO's official desktop wallet application - a privacy-focused gateway to decentralized applications (dApps) on the DERO blockchain. It provides a secure, sandboxed environment for browsing dApps whose code and data reside entirely on-chain through smart contracts. **Key Features:** - ๐Ÿ–ฅ๏ธ Desktop wallet with full GUI - ๐Ÿ”’ Privacy-focused browsing for blockchain dApps - โ›๏ธ Built-in miner (Netrunner) - ๐Ÿ” dApp authentication system (Cyberdeck) - ๐Ÿ’ฌ Encrypted messaging - ๐ŸŒ Gateway to TELA platform **Learn More:** - [Engram Introduction](/engram.md) - What is Engram? - [Engram Features](/engram/features.md) - Full feature list - [User Guide](/engram/user-guide.md) - Getting started - [Wallet Integration](/engram/wallet-integration.md) - Build for Engram **Download:** [GitHub Releases](https://github.com/DEROFDN/Engram) ### Cold Wallet (Offline Storage) Cold storage refers to keeping your private keys and wallet on an offline, air-gapped computer for maximum security. However, **DERO's account-based model makes cold storage different** from traditional cryptocurrencies. **Important:** DERO Stargate (current version) uses an **account-based model** that requires **wallet registration** on the blockchain. This makes fully offline cold storage more complex than UTXO-based coins. #### How DERO Cold Storage Works **The Challenge:** - Traditional cold wallets (Bitcoin, Monero) can be created and funded completely offline - DERO wallets **must register** on-chain before they can receive funds - Registration requires a one-time network connection **Current Cold Storage Process:** 1. **Create Wallet Offline** (Air-gapped computer) ```bash ./dero-wallet-cli-linux-amd64 # Create new wallet, save 25-word seed ``` 2. **Get Wallet Address** - Note your wallet address (starts with `dero1...`) - Write down seed phrase on paper (NOT on USB) - Save address to USB drive (safe to copy - it's public) 3. **Register Wallet** (Requires network connection) - Option A: Send DERO to the address from another wallet (auto-registers) - Option B: Temporarily connect the air-gapped wallet to register it - After registration, wallet can receive funds 4. **Return to Cold Storage** - Disconnect from network - Keep seed phrase offline and secure - Only connect when you need to send funds **View-Only Wallet:** ```bash # On any networked computer ./dero-wallet-cli-linux-amd64 # Use view-only key to check balance without exposing private keys ``` #### Best Practices for Secure Storage **Security Checklist:** - โœ… Write seed phrase on paper (NEVER digital) - โœ… Store in multiple secure locations (safe, bank vault) - โœ… Use encrypted storage for wallet files - โœ… Never expose seed to internet-connected devices - โœ… Test recovery process with small amounts first - โœ… Use strong passwords for wallet encryption ## Related Pages **Get Started:** - [DERO Tokens](/basics/tokens.md) - Understanding tokens and assets - [DERO Mining](/basics/mining.md) - Mine DERO to your wallet - [Running a Node](/basics/running-a-node.md) - Run your own node **Privacy Features:** - [Transaction Privacy](/privacy/transaction-privacy.md) - How wallet privacy works - [Homomorphic Encryption](/privacy/homomorphic-encryption.md) - Encrypted balances - [Payload Proofs](/privacy/payload-proofs.md) - Prove your transactions **For Developers:** - [Wallet RPC API](/rpc-api/wallet-rpc-api.md) - Automate wallet operations - [Smart Contracts](/smartContracts/token.md) - Deploy and interact with contracts --- --- title: "Captain Archive: DERO in His Own Words | DERO Blockchain" description: "Primary-source archive of Captain's statements on DERO's design โ€” homomorphic encryption, DVM-BASIC, consensus, governance, and protocol integrity. Sourced directly from Discord and Bitcointalk." keywords: ["Captain DERO", "CaptDero", "DERO history", "DERO-HE", "DHEBP", "DVM-BASIC", "AstroBWT", "DERO architecture", "homomorphic encryption", "DERO governance", "DERO Research License", "DERO Atlantis", "bulletproofs", "Captain quotes", "DERO founding"] date: "2026-06-04" lastUpdated: "2026-06-04" authors: ["DHEBP"] slug: "captain" canonicalUrl: "https://derod.org/captain" tags: ["captain", "archive", "history", "design", "primary-source", "DERO-HE", "DVM", "governance", "integrity"] ogTitle: "Captain Archive: DERO in His Own Words" ogDescription: "Captain's own statements on DERO design โ€” homomorphic encryption, DVM-BASIC, consensus, governance, integrity. Sourced from Discord and Bitcointalk." ogType: "article" twitterCard: "summary_large_image" twitterTitle: "Captain Archive: DERO in His Own Words" twitterDescription: "Primary-source archive of Captain's statements on DERO's design and integrity." robots: "index, follow" priority: 0.8 changefreq: "monthly" schemaType: "Article" --- # Captain Archive: DERO in His Own Words *Captain (CaptDero / captain030317) on Discord and Bitcointalk, 2017โ€“2024. Pre-2022 quotes predate the DERO-HE architectural transition.* --- ## Origins: Founding Doctrine (2017-2018) DERO's first public year on Bitcointalk reads like a project manifesto being written in real time. Between late 2017 and mid-2018, Captain (posting as CaptDero) laid out the original thesis โ€” a CryptoNote-derived chain rewritten from scratch in Go, with bulletproofs, TLS across the P2P layer, and a DAG that swallowed reorgs instead of orphaning them โ€” and made the strategic calls that shaped the project's early identity: refusing to emergency-fork away an ASIC invasion, and pivoting from the original Cryptonote codebase to the "DERO Atlantis" network. These posts predate every architectural milestone DERO is known for today. Smart contracts were still on the roadmap. Homomorphic encryption (DERO-HE) was four years away. Ring signatures, mixins, and the CryptoNote heritage described here were retired in the 2022 migration. Read this section as founding-era doctrine โ€” the engineering posture and design instincts that survived, even after the substrate they were built on did not. ### The Original ANN Thesis The Bitcointalk announcement thread is the closest thing to a founding charter. Captain frames DERO as the first chain to combine a specific stack of primitives, and commits the project to a 2018 roadmap. Bitcointalk ANN OPs are edited in place over time โ€” the version quoted here reflects the consolidated thread as it stood by mid-2018 (the same post contains a 'Full Premine intact as of 12 July 2018' line and references the post-April Atlantis network), not the verbatim December 2017 first post. The Dero Project has written a unique new blockchain technology that is based on the Dag and CryptoNote protocol with double spend protection. Dero's goal is to create a unique state of the art blockchain technology with enhanced reliability, privacy, security, usability, and portability by bringing together some of the best proven technologies like the CryptoNote protocol and smart contracts, thereby allowing for the creation of truly private smart contracts. The Dero development team has implemented complete SSL across the Dero network which is a first on any blockchain. [...] First blockchain to have: DeroDAG + Cryptonote + Bulletproofs + Complete SSL + POW. Blocktime 12 secs + Confirmation times 2 mins. Traditional 51% attacks are not possible on DERO network. Dero is one of the very few blockchains built from scratch [...] DERO blockchain has the following salient features: - DAG Based: No orphan blocks, No soft-forks. - 12 Second Block time. - Extremely fast transactions with 2 minutes confirmation time. - SSL/TLS P2P Network. - CryptoNote: Fully Encrypted Blockchain - BulletProofs: Zero Knowledge range-proofs (NIZK). - Ring signatures. - Fully Auditable Supply. - DERO blockchain is written from scratch in Golang. Two design commitments here outlived everything else in the post: the from-scratch Go rewrite, and the insistence on auditable supply. The CryptoNote substrate, ring signatures, and the 12-second block time were all replaced in the DERO-HE migration (2022), which moved DERO to homomorphic encryption with an 18-second block time. The roadmap dates in the original post are obviously historical. ### Status Report: 44 Days Into the Go Rewrite Six weeks after the announcement, Captain posted a component-by-component status update on the from-scratch Go daemon โ€” wire protocol, consensus, the ringct primitives, BoltDB. Read it as a checklist of what "built from scratch" actually meant in practice. In the status update release 1, Following parts of cryptonote has been rewritten in golang. At present, Golang DERO daemon can sync and verify blockchain with the existing DERO network. [...] **Cryptonight Hash:** This is an ASIC resistant, memory-bound algorithm. [...] **Wire protocol (90% completed):** This protocol is used to exchange data between 2 DERO daemon nodes. At this point, Go daemon can connect to C daemon and vice-versa, sync blockchain and exchange, already possible. Complete interoperability has been achieved. [...] **Pederson Commitment** (Part of ring confidential transactions): [...] a cryptographic primitive that allows user to commit to a chosen value while keeping it hidden to others. [...] **Borromean Signature** (Part of ring confidential transactions): Borromean Signatures are used to prove that the commitment has a specific value, without revealing the value itself. **Additive Homomorphic Encryption:** [...] used to prove that sum of encrypted Input transaction amounts is EQUAL to sum of encrypted output amounts. [...] **MLSAG** (Work-in-Progress): MLSAG gives DERO untraceability and increases privacy and fungibility. [...] **BOLT Database:** DERO Blockchain uses BoltDB for future scalability and low latency reads. ### Engineering Self-Description: Bulletproofs, Batched and Optimized Inviting the community to audit the source, Captain attached a self-description of the bulletproofs work. It is one of the rare moments where the project's engineering posture โ€” measure, optimize, batch, attribute โ€” is laid out in his own voice. Secure and fast crypto is the basic necessity of this project and adequate amount of time has been devoted to develop/study/implement/audit it. [...] As far as the Bulletproofs are considered, since DERO is the first one to implement/deploy, they have been given a more detailed look. First, a bare bones bulletproofs was implemented, then implementations in development were studied (Benedict Bunz, XMR, Dalek Bulletproofs) and thus improving our own implementation. Some new improvements were discovered and implemented [...]. Major improvements are in the Double-Base Double-Scalar Multiplication while validating bulletproofs. A typical bulletproof takes ~15-17 ms to verify. Optimized bulletproofs takes ~1 to ~2 ms (simple bulletproof, no aggregate/batching). Since, in the case of bulletproofs the bases are fixed, we can use precompute table to convert 64*2 Base Scalar multiplication into doublings and additions (NOTE: We do not use Bos-Coster/Pippienger methods). This time can be again easily decreased to .5 ms with some more optimizations. With batching and aggregation, 5000 range-proofs (~2500 TX) can be easily verified on even a laptop. The implementation for bulletproofs is in `github.com/deroproject/derosuite/crypto/ringct/bulletproof.go`, optimized version is in `github.com/deroproject/derosuite/crypto/ringct/bulletproof_ultrafast.go`. ### Absorbing the ASIC Invasion as a Free Stress Test When ASICs landed on the early DERO network, the obvious response was to fork the algorithm immediately. Captain made the opposite call: treat the attack as a load test, ship the next milestone on schedule, and announce a pivot to "DERO Atlantis" instead of a panic patch. Thanks [Speedie] for your time and efforts for understanding and explaining the same. Everyone was more than happy and satisfied with Golang Alpha release and no one would have ever required/asked for more than what was already being offered. Everything was moving ahead of schedule and smooth. But we decided to go for **DERO Atlantis** as we can see clearly the journey ahead. ### What the Privacy Layer Was Actually For Replying to a community essay (by the user *fellestreum*) that articulated DERO's privacy thesis better than any whitepaper line, Captain endorsed it openly. This is one of the few places where the project's social purpose โ€” not the engineering โ€” gets stated in his voice. This post deserves much more than thank you and sMerit. thank you [fellestreum]. You have expressed the IDEA behind Dero. We hope to create a Blockchain which will affect the entire society from increasing the privacy to daily utilities. Users will have confidence that no copy/access of his data exists on the shops/counters/merchants/agents he has visited since start of the day. He lives a private life and he knows who has access/copy of his data. This is a very big and huge impacting topic. In parallel to technological development of DERO Blockchain we are also working for practical life example to express the DERO concept. ### Why DERO exists โ€” the 2023 retrospective This one quote breaks the section's 2017-2018 framing on purpose. In April 2023, with five years of DERO development behind him and the founding thesis having played out across the Atlantis-to-Stargate migration, Captain compressed the original *why* into two numbered bullets โ€” a retrospective restatement that maps cleanly onto the ANN OP at the top of this section. It is included here because it answers the same question the 2017 thread opened with, in 2023's vocabulary. DERO was designed due to short comings of Bitcoin, particularly: 1] Bitcoin has no privacy, missing non-fungibility & no ability to hide/protect it's senders & receivers from public records. 2] Lack of programmability(Smart Contracts). Also it was impossible to push privacy feature in BTC code due to lack of interest in core DEVS with respect to privacy. The two-point indictment is straightforward โ€” privacy and programmability are the gaps the project was built to fill. The third sentence is the one worth pausing on: it is Captain saying, in plain language, that he did not believe privacy could ever be added *upstream* of where DERO already sat. The implication is not that Bitcoin is the wrong tool for some users; the implication is that the people maintaining Bitcoin would not accept the change DERO is, so the change had to ship as a separate chain. --- ## Protocol Design Decisions The three quotes in this section come from different years (2018, 2022, 2023) but share a single posture: when a feature feels obviously missing โ€” HTTPS on the daemon, a chain-side search API, looser query limits โ€” the answer is usually that the absence is the design, not the omission. Each post argues from the threat model down, not from convenience up. ### Why the daemon doesn't ship HTTPS A recurring request from newcomers was that the daemon JSON-RPC should be served over HTTPS. Captain's standing reply, posted in `#technical-questions` in late 2022, treats HTTPS as a misplaced trust anchor rather than a security upgrade. https is not supported intentionally. HTTPS gives false sense of security as certificate issuer has the private key to decrypt the traffic. And issuer can share the private-keys to others also when required. https can only help with local ISP/telecom sniffing, In that case use vpn etc.. The argument is the CA-trust critique: a CA-issued certificate gives the issuer (and anyone they hand the key to) the ability to decrypt the traffic. For an RPC endpoint that you should already trust at the wire level โ€” your own daemon, on your own machine, behind your own VPN โ€” HTTPS adds an additional trusted party rather than removing one. ### DAG propagation, uncles, and where conflict rules live In the project's first year, a deep-dive Q&A in `#technical-questions` walked through six questions about DERO's then-architecture. Three of Captain's answers are still operative today: where conflict resolution lives (the client protocol, not the consensus rule), how side blocks count, and an honest admission about the proof-of-work search. Ans 2: Dero DAG like other chains requires block propgation time to propgate blocks. Block propgation times AVGs 99.99% ~15 seconds. Ans 3: By client protocol. Ans 4: 2 uncles (Dero side blocks if you are referring to them only) are allowed depending on NW. Ans 5: RingCT is core part of Dero architecture. Ans 6: We are still searching better algo than POW. "Ans 5" is the time-locked line โ€” RingCT was the privacy primitive of pre-2022 DERO and was retired in the DERO-HE migration. "Ans 3" and "Ans 4" are still load-bearing: conflict resolution lives in the client protocol layer, and DERO still treats side blocks as first-class citizens (not orphans) up to a network-determined cap. ### Resource exhaustion is not a bug to patch When the Bitcoin Ordinals surge stressed node operators in early 2023, the question came up in `#dero-discussion`: shouldn't DERO just raise its limits so clients can request larger ranges of chain data? Captain's answer reframed the request as a category error. As with the Bitcoin Network issue recently in news if you will ask entire chain of data then nodes are being going to be overloaded eventually. There is no good fix to solve this permanently. We can increase the RAM/resources limit however keep in mind they are finite & can be consumed by asking for more & more data to consume the increased resources. It is like just asking the webserver to serve more users beyond capacity. Captain treats unbounded query limits as the bug, not the limit itself. Any resource ceiling is a moving target as long as the network is willing to fulfill arbitrary-size requests โ€” the only stable answer is to bound what clients can ask for in the first place. This is the same philosophy that lives in DERO's current `--mine-block-uncle-limit`, `--p2p-tx-batch`, and similar knobs: hard ceilings rather than dynamic scaling. --- ## Privacy & Homomorphic Encryption The defining bet behind DERO-HE is that privacy should not be a layer of obfuscation bolted onto a transparent ledger, but a property of the cryptography itself. Across late 2021 and 2022 โ€” spanning the testnet rollout of the new account-model chain and the year that followed mainnet migration โ€” Captain returned again and again to the same point: balances and transfers live as ElGamal ciphertexts, every operation runs over encrypted data, and there is no master key, view key, or audit hatch that lets anyone other than the seed-holder read an account. The quotes below trace that thesis from its highest-level statement down to the specific mechanics: why the account model is itself a privacy feature, what the wallet actually does when it opens, how DHEBP nonces prevent double-spends without outputs to track, and how the same homomorphic guarantees extend to every native asset on the chain. ### Homomorphic encryption replaces the entire obfuscation stack Two weeks before the DERO-HE mainnet upgrade, Captain spelled out the thesis in a single paragraph: nothing on the chain is ever observable in plaintext, not even briefly. Yes absolutely. HE encryption replacing all obfuscation stack completely. No more obfuscations on DERO network now. No one will be able to see/confirm your data on DERO blockchain without your seed/wallet. All operations will be on encrypted data only. So no requirement/gimmick to ask for your data to be in decrypted state ever. Not even once your data will ever be in decrypted state. This is the cleanest one-paragraph statement of the DERO-HE design goal. "Obfuscation stack" is the ring-signatures / stealth-addresses / view-keys approach used by Monero-family chains; Captain's claim is that HE makes that whole apparatus unnecessary because the ciphertexts themselves are the privacy boundary. ### Even the wallet has to compute to know its own balance In a #dapps thread comparing DERO to public-ledger smart-contract platforms, Captain pushed back on the comparison by pointing at what "private balance" actually costs the wallet itself. There is no point in comparing DERO with ADA/ETH as DERO balances are private unlike public blockchains. There is no way in DERO you can know any other account balances. DERO-wallet has to run lots of computations to know it's own balance. So basically there is no way you can know balances of other DERO wallets. There would be no point of DERO privacy if thats possible. The line "DERO-wallet has to run lots of computations to know it's own balance" is the tell. The wallet receives an encrypted balance and has to decrypt it locally using the spend key โ€” there is no plaintext figure cached anywhere on the network to read. If the wallet could shortcut that, so could everyone else. ### No master key, and only 66 bytes from the network to open a wallet Responding to a recurring "who holds the keys" question in #dero-discussion, Captain laid out what a wallet actually needs from the chain to function. There is no concept of any master private/secret key on DERO. DERO creates a elgamal balance ciphertext associated to any wallet-account. The private key is NOT broken or distributed among other nodes in any way or form. When user opens wallet, no communication with DERO network except 66 bytes are required. This process is completely done within wallet and is not linked with DERO network. As DERO is account model, Only 66 bytes are required by wallet from DERO blockchain to operate. Blocks & transactions are required to create & maintain history on DERO network. Captain does not spell out what the 66 bytes are in this message โ€” only that the wallet needs that much from the chain, and nothing else, to operate. The size is consistent with an ElGamal balance ciphertext (two compressed curve points), but treat that as inference rather than Captain's claim. The structural point stands either way: full blocks and transactions exist to maintain network history, not to make a wallet functional. ### The account model is itself a privacy feature A few months after mainnet, Captain framed the account-vs-UTXO choice as a privacy decision, not just an engineering one. Another privacy enhancing part of DERO is it's account model. You can drop the entire transactions logs anytime from DERO database like(--fastsync) & DERO will still work unlike Monero which requires scanning/tracking/recording of key-images from first transaction. After dropping you will never abile to do any statistical analysis as there will be no such data. Because state lives in account ciphertexts rather than a forever-growing set of unspent outputs and key-images, history is disposable from a node's point of view. A pruned node can still validate and transact; anyone hoping to do retroactive chain analysis on the dropped data simply has nothing to analyze. ### DHEBP: building on Zether, then past it During the DERO-HE testnet, the contributor vanitas was reading the transaction-build code and asking how proofs bind to height. Captain confirmed the mechanism and named the protocol. [vanitas asked, paraphrased: u and u1 in transaction_build.go appear to be curve points tied to height and a sender secret; u1 also includes block batch size. How is this used to prevent double-spends, and how does it interact with the DAG?] Yes, u and u1 are set to a curve point represent height at which TX was build. Height is mentioned in the TX. This value is calculated at run-time by blockchain to verify the the claim by the TX originator. DHEBP protocol and design is an improvement over zether/anonymous zether. DHEBP โ€” DERO Homomorphic Encryption Blockchain Protocol โ€” is the in-house protocol that ships in DERO-HE. Captain situates it as a descendant of Bunz et al.'s Zether and Anonymous Zether work. The u/u1 curve points bind each transaction to the height it was built at, and the chain recomputes the expected value at verification time to confirm the originator's claim. ### What "double-spend" even means without outputs vanitas followed up with the right structural question: in an account model with no UTXOs, what does double-spend prevention actually look like? Captain answered with the bank analogy. [vanitas asked, paraphrased: if the nonce ties to height plus a secret, can the same tx repeat at a different height with a different nonce? Or is the question moot under an account model โ€” and what is a double-spend attack when there are no outputs to double-spend?] Nonce prevents not only the same TX but also any other TX from the same secret owner at the same time. In DHEBP basically TX is just an entry with deductions and additions. Nonces are used to prevent duplicate and/or double spend attacks. In simple terms, Assume that DERO blockchain acts as bank to which users submit TXs and the DERO blockchain filters out invalid/incorrect/stale TXs and processes only valid TXs that too one at a time. The mental model is double-entry bookkeeping under encryption: a transaction is a deduction-plus-addition pair, and the height-bound nonce ensures only one transaction per account can be admitted per slot. There is nothing to "spend twice" because there are no outputs โ€” just an account ciphertext that the chain refuses to mutate more than once at a time. ### Same homomorphic guarantees for every native asset Earlier in the same testnet conversation, vanitas noticed that `Payloads[0]` looked special and wondered if it represented the native DERO asset. Captain confirmed and generalized. [vanitas observed: Payloads[0] is referenced in multiple places โ€” possibly the native DERO asset, or something about the tx itself; the payloads appear to map to specific SC assets.] DERO supports multiple (~ 2 ^ 256 ) native assets. DERO itself is a native asset with SCID "000000..000000". However, most users will use the native DERO asset. Also all assets are backed by the same homomorphic guarantees and cryptography.. Eg. We need to write DERO if we are using native "DERO" asset, For others we need to write "TOKEN" etc. Worth holding onto: any token issued on DERO inherits the same encrypted-balance semantics as DERO itself. There is no "transparent token" tier โ€” every native asset, identified by its 256-bit SCID, ships with the same ElGamal/HE protection. The zero SCID is just the convention for the base asset. --- ## DVM, Smart Contracts, and DVM-BASIC The DERO Virtual Machine has always been a deliberately small target. Where most smart-contract platforms ship a sprawling instruction set and let developers reach for whatever abstraction feels natural, Captain stripped DVM-BASIC down to a handful of types, a single jump primitive, and a tight contract for how calls land in a block. The quotes below โ€” drawn mostly from 2019 through 2022, spanning the original mainnet contract experiments and the DERO-HE testnet that became Stargate โ€” lay out the reasoning behind those constraints. Read them as a worldview rather than a feature list: GOTO is enough because everything compiles to it anyway, fund movement into a contract is a burn rather than a transfer, search belongs on your node and not on consensus, and ordering inside a block is a guarantee the protocol owes you. The language reference in the middle is the closest thing to an official DVM-BASIC spec Captain published in chat. ### GOTO is the building block, not a smell DVM-BASIC ships with `GOTO` and no `for`, `while`, or `switch`. Newcomers regularly read this as a missing feature. Captain's standing reply is that the criticism mistakes a high-level convenience for a primitive. GOTO is basic building block of any computing CHIP atm. if you cannot see it directly it doesn't mean it doesn't exists. Every switch-case, break, loop etc. all are implemented in form of GOTO. Rest all is propganda. The design choice is enduring: every DVM-BASIC contract written today still expresses loops and branches as labeled `GOTO` targets, and the verifier benefits from the smaller surface. If the absence of `for` loops feels wrong, the lesson is to write the jump explicitly rather than wait for sugar that is not coming. ### The DVM-BASIC language contract During the DERO-HE testnet, Captain posted what amounts to a one-screen language reference for DVM-BASIC, pointing at the in-repo guide on GitHub at the time. https://github.com/deroproject/derohe/tree/main/guide#dvm-interprets-the-smart-contract-and-processes-the-sc-line-line ``` DVM interprets the smart-contract and processes the SC line-line uint64 supports almost all operators namely +,-,*,/,% uint64 support following bitwise operators & ,|, ^, ! , >> , << uint64 supports following logical operators >, >= , <, <=, == , != string supports only + operator. string support concatenation with a uint64. string supports ==, != logical operators. All DVM variables are mandatory to define and are initialized to default values namely 0 and "". A SC execution must return 0 to persist any changes made during execution. During execution, no panics should occur. ``` The behavior described here still holds on Stargate: two types (`Uint64` and `String`), mandatory declaration with zero/empty defaults, line-by-line interpretation, and the rule that a non-zero return โ€” or any panic โ€” rolls back every state change in the call. The `derohe/guide` path Captain linked in 2021 no longer resolves; the equivalent material today lives in the `dvm/` package source and in the DVM-BASIC reference on the dero-docs site. ### Funds sent to a contract are burned, not deposited A recurring point of confusion on the DERO-HE testnet was what it means to "send DERO to a smart contract." Captain reframed the mental model away from the EVM-style deposit. It's more of burning than deposit or transfer because when you transfer some DERO from any wallet to SC this amount gets burned from the DERO Network and comes into the Smart Contract universe where it is open and visible to all. And this transferred amount is not accounted in DERO network unless it gets back to DERO Network from SC. This is one of the most important conceptual differences between DVM and EVM. Funds inside the contract universe are public and accounted to the contract; they only re-enter the encrypted DERO supply when a contract explicitly sends them out via `SEND_DERO_TO_ADDRESS`. The model still governs how contracts handle escrow, payouts, and reserve accounting on Stargate. ### Ordering guarantees inside a block When developers started building higher-throughput dApps, the question of what the chain actually promises about call ordering came up. Captain laid out the contract in four lines. A contract can accept n contract calls per block. A single txn can only dispatch a single call. Contract can accept n calls per signer per block. Above are guarantees of order. These are the rules contract authors should design against: one call per transaction, multiple calls per signer per block, and ordered execution within the block. Anything that requires batching multiple state mutations atomically has to be expressed as a single call inside the contract โ€” not assembled out of several transactions. ### Keep search off-chain Asked about adding richer query and search capabilities at the protocol layer, Captain pushed back on the premise. It will bring lots of complexities if we bring extra processing to blockchain. It would be better if we do all search/similar operations on your local node. Anyways will dig deep if we can add some small and less complex functions. This is the philosophy that produced the local-node-first tooling we have today: Gnomon indexing on the operator's machine, TELA discovery via the publisher bridge, and clients that walk the chain themselves rather than asking consensus to do it for them. The chain stays small; the smarts live at the edge. ### Some features are missing on purpose A user, lifetyper, asked whether arbitrary message payloads could be stuffed into transactions to deliver private messages. Captain answered with a posture rather than a feature flag. How long do you expect Dero Network will survive after such features are implemented before everyone comes after it. Let me speak today almost all of the missing features discussed/asked above in this channel are not due to lack of technical exoertise/capabilities. Read in context, this is less a feature-gap admission than a survival-posture statement: in 2019 Captain weighed feature additions against how the network would be perceived and attacked, not just against design cleanliness. Stargate later shipped encrypted RPC arguments and account-bound messaging patterns under a very different threat model โ€” not a direct fulfillment of the plaintext message-stuffing the questioner asked about here. --- ## Consensus, DAG Ordering & Mining Policy This section covers two related-but-distinct strands of DERO's chain design. The first is how the ledger is *ordered*: not as a strictly linear chain, but as a DAG in which side blocks are first-class citizens counted into a separate topological height. The second is how the team approaches *mining* โ€” specifically, a stated willingness to change the proof-of-work algorithm when they judge it necessary, as demonstrated by the Stargate-95 hard fork and Captain's follow-up to miners who pushed back on it. The quotes span 2018 through mid-2022. The earliest message predates the 2022 DERO-HE migration; the mechanics it describes (chain height, topo height, side blocks) survived that migration largely intact, but the prompt output and block numbers it references are from the pre-Stargate codebase. ### Reading the daemon prompt: chain height, topo height, and side blocks Early node operators were confused by the four numbers DERO's daemon printed at the prompt. In mid-2018 Captain walked through them in #technical-questions and used the explanation to introduce the DAG concept that distinguishes DERO from a strictly linear chain. Explanation DERO prompt: `DERO:A->100861/B->101420 [C->100861/D->101420]` where A-> Current chain height of local node. B-> Current chain Topo height of local node. C-> Network median chain height of connected/visible peers to local node. D-> Network median chain Top height of connected/visible peers to local node. Topo height: Dag topological ordered height. Dero side blocks: D-C or B-A. Contributes to chain security and increased scalability. Expected 10-15%. The distinction between *chain height* (the main sequence) and *topo height* (the DAG-ordered count including side blocks) is the load-bearing concept here: side blocks are not orphans to be thrown away, they are first-class citizens that contribute hashpower to security. The specific block numbers and prompt format belong to the pre-Stargate (pre-2022) daemon, but the height/topo-height/side-block model still describes how DERO orders its ledger today. ### Stargate-95: the AstroBWT v3 hard fork In June 2022, Captain announced a mandatory hard fork at block 481600. The release rotated DERO's PoW to AstroBWT v3 and temporarily restricted mining to the official CPU miner until third-party miners (XMRig and the GPU ports) could catch up. @here New version of DERO Stargate-95 released. Update is mandatory as this release is HardFork. Please update your DERO daemon and official miner. No need to delete any file, Just update the derod-daemon (exit the daemon, miner & wallet gracefully. Download, extract & replace the files. After replace start again.). POW is changed to AstroBWT v3. Use official miner only for next few days till other/GPU miners are updated. Only CPU miner is released atm. XMRig etc. are not updated atm. https://github.com/deroproject/derohe/releases/tag/Release95 HardFork will happen in next few hrs at block 481600 . Stargate-95 is the canonical example of DERO's mining policy in motion: a PoW change shipped as a hard fork on a few hours' notice, with the explicit expectation that the third-party miner ecosystem would catch up afterward rather than gate the rollout. The Release95 tag and the AstroBWT v3 algorithm are still live on mainnet. ### Why the algorithm keeps moving Six days after the Stargate-95 fork, miners who had built around the old algorithm pushed back in #dero-mining. Captain's response framed the change as a deliberate policy choice: DERO will keep experimenting, and will rotate the algorithm again when the team judges it necessary. Yes we are well aware of above scenarios. But we would like to make very clear that just because someone is not happy with new updates/changes/releases DERO will not stop experimenting new ideas/technologies. We are at very early stage & we need to fix/upgrade lots of things. There was no point in continuing old ALGO when only few were taking advantage of that. We will change the ALGO again if required. Captain doesn't specify who the "few" were โ€” whether they were running optimized private miners, dominant pools, specialized hardware, or something else โ€” only that the previous algorithm had narrowed to a small group's benefit and that this was reason enough to rotate it. The closing line ("We will change the ALGO again if required") is the durable statement of policy: the design surface is treated as in-progress, and the willingness to fork again is the feature, not the bug. --- ## Governance & Community Contributions DERO's development has always run through a small core team, but in May 2023 Captain formalized a path for outside contributors. The mechanism was deliberately narrow โ€” two named branches, a clear split between "fits the current vision" and "requires a hardfork," and a single license under which any external code would be accepted. The statements below are from that May 20, 2023 announcement, posted in parallel to `#dero-discussion` and `#announcement` (the two messages are duplicates of each other). They remain the most explicit public description of how Captain intended community code to enter the project. No follow-up governance document has been published since Captain went MIA in January 2024, so this framing is what's on the record โ€” as a 2023 plan, not as a workflow that ever visibly operated. ### The two-branch model for community contributions Captain laid out the structure in a single message, distinguishing minor improvements from changes that would require a hardfork. The same text went up in `#dero-discussion` first and then in `#announcement` about 37 minutes later โ€” the version below is the announcement-channel post. Respected DERO Members, To incoporate community development in DERO Project two community branches has been planned. Community-mainnet(for mainnet) & community-testnet(for testnet) branches. DERO Community DEVs can create commits for above branches and after testing & discussions commits will be migrated/merged to main mainnet branch. Community-mainnet(for mainnet) branch will be used for commits that are minor & doesn't require hardfork or substantial change in the current codebase/vision. Community-testnet(for testnet) branch will be used for commits like that are entirely new concept, experimental in nature & require hardfork. This branch can be used to test ideas like removal of account registration requirement or support of Inter communication between Smart Contracts on DERO network. Any code published/committed will be accepted under DERO Research License only. Thank you all of you. Captain The split is the substantive part: `community-mainnet` is the on-ramp for changes that fit the existing protocol, and `community-testnet` is a sandbox for ideas big enough to need a hardfork. The two examples Captain names for the testnet branch โ€” dropping mandatory account registration, and inter-contract communication โ€” are concrete signals about what he considered protocol-level open questions in 2023, not casual asides. In practice, this branch model never produced a visible community-contribution pipeline before Captain went MIA in January 2024, and no merges from those branches into mainnet were ever announced. Read this as the 2023 plan of record, not as an active intake path a contributor can use today. --- ## Protocol Integrity: Captain in His Own Words DERO's economics have been the target of recurring claims about a hidden dev tax, premine, or skimmed block rewards. The clearest rebuttal isn't a third-party doc โ€” it's Captain directly addressing the question in `#technical-questions` and pointing readers back at the code. This section anchors the integrity record on a primary source: Captain's own statement of how main-block and side-block rewards actually work. The quote below is from late 2021, before the DERO-HE migration, but the reward structure it describes is the same one operating on mainnet today. ### No Dev Tax โ€” 100% to Miners, 8% on Side Blocks as a Time-Sync Incentive Asked in `#technical-questions` about the existence of a developer tax baked into block rewards, Captain answered bluntly and pointed at the code: There is no such thing as DEV TAX etc. , Pls read the code carefully again. Main block rewards are full 100% and side block reward are 8% and both rewards goes fully to to miners. Side block has 8% rewards to force miners to sync their time and update/submit their job on time. Two things to take away. First: main-block rewards are 100% miner, side-block rewards are 8% miner, and nothing is siphoned off to a developer address โ€” this is verifiable directly in the consensus code. Second: the 8% side-block reward isn't charity, it's a mechanism. It pays miners to keep their clocks synced and submit jobs on time, which matters for a chain that uses a DAG-aware structure rather than a strict longest-chain rule. This statement predates the late-2022 DERO-HE migration, but the reward structure it describes โ€” main 100%, side 8%, no dev cut โ€” is the same one in force on mainnet today. --- ## Philosophy & Inspirational Quotes The technical work has its own page. This one is for the posture behind it โ€” why Captain built DERO the way he did, what he expected of the community, and the values he kept restating across seven years of public messages. The lines collected here are not slogans drafted for a website. They are answers given inside development channels, in support threads, in replies to skeptics and well-wishers alike. Read in sequence, a coherent project ethos emerges: privacy is not optional, the network is not anyone's property, the work is hard on purpose, and the community โ€” not the core devs โ€” is the long-term guardian. ### We choose the hard way Day one of the bitcointalk announcement thread. A poster thanks Captain for the work, and Captain answers with what reads, in hindsight, as the project's founding posture. thanks, you are welcome, we have the skills and we choose the hard way its better for whole crypto community if there are any advancements. The frame is set in one sentence: the team is capable, the path is deliberately hard, and the justification is that the broader ecosystem benefits when somebody actually pushes the cryptography forward. Every later design choice โ€” Bulletproofs, homomorphic encryption, no optional-privacy toggle โ€” is downstream of this line. ### Not an ICO. A community project. Ten days into the bitcointalk thread, with the usual ICO-era questions arriving, Captain draws the line on what DERO is and is not. Will be updated in details and this is not ICO. Community project where everyone is invited to contribute. The contributor-led framing is staked out before there is much of a community to lead it. This becomes the structural reason DERO never had a foundation, a treasury, or a token sale to point at. ### Why DERO, in plain language Two months in, Captain writes out the canonical answer to the question that would follow the project for years: why does a smart-contract chain need privacy at all? He skips the jargon and reaches for a door. WHY DERO AND WHY SMART CONTRACTS NEED PRIVACY ? In very simple and few words: Assume you design a smart contract and integrate to access/authorize a building/open a door or any other service like asset-management/tickets/shares distribution based on smart contract. Many would not like like to share/view details of all other users/customers who used/participated/access that contract/service. I hope you too would like transparency in contract details but would not like to share/disclose your details to rest of the world. On DERO blockchain smart contracts details are transparent on blockchain but not user details. The split he names โ€” transparent contract logic, private user data โ€” is the architecture DERO eventually shipped. The mission was articulated before the engine to deliver it existed. ### A blockchain that affects society Three weeks later in the same thread, Captain expands on the social vision in the most sweeping mission statement of the early archive. You have expressed the IDEA behind Dero. We hope to create a Blockchain which will affect the entire society from increasing the privacy to daily utilities. Users will have confidence that no copy/access of his data exists on the shops/counters/merchants/agents he has visited since start of the day. He lives a private life and he knows who has access/copy of his data. This is a very big and huge impacting topic. In parallel to technological development of DERO Blockchain we are also working for practical life example to express the DERO concept. The scope is deliberately wider than crypto: a person walks through their day and knows who has copies of their data. Privacy as a daily-life property, not a coin feature. ### No permission needed, no mercy asked September 2020, in technical-questions. A user asks about official cooperation or partnership for a business that wants to integrate DERO. The answer is short. In Crypto DERO doesn't need/expect any mercy or so of any kind. Also you don't need DERO permission for any cooperation to use DERO in your business as DERO is opensource and you can find all code/API on github. Permissionless on both sides โ€” the project asks nothing from anyone, and nobody needs to ask anything of the project. The codebase is the API; that is the entire relationship. ### Not anti-anyone. Pro-users. April 2022, in #random. A familiar question surfaces โ€” is DERO trying to replace X, beat Y, kill Z? Captain reframes the entire posture. DERO have no interested in fear or making somone obsolete . Objective is very clear that users using DERO should have max privacy & security. The mission is not competitive. It is internal: maximum privacy and security for the people who use the chain. Everything else is noise. ### No optional privacy The next day, in error-support, a user worries they might leak information by misusing the wallet. Captain answers with what is essentially the design ethos of the protocol in one sentence. There is no concept of optional privacy in DERO. So don't worry of loosing/degrading privacy in DERO if you are doing something wrong. Privacy is not a toggle, a tier, or a careful-mode. It is structural โ€” you cannot use the chain incorrectly in a way that leaks user data, because there is no shielded/transparent split to misuse. ### On false privacy and VCs A week later, in #suggestions, the discussion turns to projects that market themselves as private but are closed-source or VC-backed. Captain states the values position directly. DERO would never risk its users in false sense of privacy. Secret blockchain is blackbox-closed source technology with VCs. And VCs have only one goal. The bar is not whether something is marketed as private. It is whether the user can verify it. Two sentences capture the anti-blackbox, anti-extractive-funding stance of the project. ### Privacy as a requirement February 2023, in #trading, against a backdrop of tightening surveillance regimes and exchange collapses. Captain offers one of his shorter and more pointed lines. We will soon see the requirement of privacy & freedom. Eight words. Privacy and freedom not framed as features to offer, but as requirements to meet. The reframing is the whole point. ### Core devs will never be part of some centralized thing April 2023, in #dero-mining. A user asks about seed nodes and whether they create a centralization risk. Captain uses the answer to draw a wider line. DERO seed nodes are not required except to bootstrap network. DERO is actual decentralized network & will remain so. DERO core devs will never be part of some centralized thing. There are so many other protocols & chains which can be freezed/halted/selective, feel free to join those networks. Seed nodes are convenience, not control. The closing line โ€” that other protocols exist for anyone who wants freezable, halted, or selective behavior โ€” is the project's posture in one breath. --- --- ## Quantum Resistance & DERO-QR Quantum resistance is one of the few topics where Captain spoke about a future DERO upgrade in concrete engineering terms. The plan, surfaced in a March 2022 exchange with community member Robyer, is DERO-QR โ€” a quantum-resistant scheme that lands on the existing DERO network, with GravitonDB acting as the migration substrate from DERO-HE to DERO-QR. The supporting context stretches back to 2020, when Captain first pointed at Graviton as the reason DERO could move state under cryptographic proofs at all, and forward into mid-2022, when he kept the threat surface in view by quietly sharing news of broken "quantum-safe" schemes. Captain's posture is consistent throughout: quantum is a "when needed" problem, the real threat is selective and hidden, and the migration tooling is already in the tree. ### State tracking with crypto-backed proofs Two minutes later in the same thread, Captain names Graviton's actual design intent โ€” not just storage, but verifiable state. So GravitonDB was written for state tracking with crypto backed proofs. This is the property that makes the later DERO-QR migration plausible. A database that already commits to state under cryptographic proofs can re-map that state under a different cryptographic scheme without breaking the chain of custody. ### Opening posture: not a big deal Jump forward to March 31, 2022. A discussion about quantum threats opens in #trading, and Captain sets the tone with a single line. DERO will have Quantum Tech when it will be required. It's not a big deal. The framing is deliberate. Quantum is a when-needed problem, not a panic โ€” but the rest of the thread shows he is already engineering for it. ### Threat surface: hacker's garage, IBM, Intel Robyer pushes back with the standard academic timeline argument โ€” large-scale quantum computers are years away. Captain redirects to where the real threat actually lives. Robyer you may be right but Pls don't underestimate hacker's garage. And also go though IBM/Intel's recent innovations list. Two threat vectors in one line โ€” corporate R&D pipelines and unannounced private capability. Neither shows up in conference papers, and both can be operational long before the public timeline says they should be. ### DERO-QR on the current network Fifteen minutes later, Captain drops the keystone announcement. This is the most concrete public statement of DERO's quantum-resistance plan. Robyer, We are ready, You will have DERO-QR(Quantum-Resistant) on current DERO-NW. GravitonDB will help to internal-map exisitng DERO-HE to DERO-QR. Three engineering claims compressed into one sentence: DERO-QR will run on the existing network (no fork, no new chain), the upgrade path is DERO-HE to DERO-QR, and GravitonDB is the substrate that does the internal mapping between the two cryptographic regimes. The 2020 Graviton work is what makes this an upgrade rather than a migration. ### Enigma-cracking: you won't know until you do Later in the same thread Captain reaches for a historical analog to explain why quantum capability will not announce itself. Exactly, Most things will be down. But expect attacks to be very selective and occasional just like as Robyer said above Eg: Enigma cracking so you will never know till mass attacks in open. The Enigma analogy is the load-bearing one. Bletchley Park's capability stayed secret for decades while it was used selectively to avoid revealing the break. A real quantum capability would behave the same way โ€” visible only when the operator decides the strategic value of using it openly exceeds the value of keeping it hidden. By then the migration window is closed. ### GravitonDB is a complete project in itself September 2022, in #dero-discussion, Captain reframes how to think about Graviton's scope inside the DERO codebase. GravitonDB which is complete project in itself is side project for DERO-HE. Read alongside the March quotes, this lands differently than it might in isolation. Graviton is a standalone project that happens to currently serve DERO-HE โ€” which is exactly what you would want if you planned to swap the cryptographic layer above it for something quantum-resistant without rewriting the storage and proof substrate underneath. --- ## Current & Coming Times: What Ships vs What's Ready There is a recurring theme in Captain's posts that is easy to miss if you only read DERO's release notes: what ships is deliberately less than what is built. Stargate, in his telling, is a *downgrade* โ€” tuned for the machines on the network today and for users who need to understand what they are running. The harder primitives sit behind it, waiting. Read together, these messages frame DERO not as a finished product but as a design horizon. The privacy is sized for "current & coming times," the architecture is backed by "decades of experience," and the AI-agent future Captain described in 2022 reads, in 2026, less like speculation and more like a roadmap. ### Downgrades for current times and weak machines Asked in August 2022 about homomorphically encrypting addresses, Captain answers in a single beat โ€” it is not the hard part. The hard part is restraint. ``How hard would it be to Homomorphically encrypt addresses?`` Not a big deal, Lots of downgrades have been done to DHEBP for keeping in view of current times & computational powers of weak machines on NW. The line to sit with is *Lots of downgrades have been done to DHEBP*. The shipped protocol is not the ceiling of what was designed โ€” it is the floor that the weakest machine on the network can still keep up with. ### Designed from scratch, because the field stalled Four minutes later, Captain explains why those downgrades exist in the first place: there was nothing serious to build on. Lots of new things have to be designed in DERO from scratch for maximum privacy. There is nothing in existing blockchain tech world to develop something serious. Blockchain research & progress haven been neglected/over-taken due to hype & scams. This is the frame for every other quote in this section. DERO is not assembling other people's primitives. It is building the primitives, and shipping a tuned-down version of them so the network can actually run. ### AI making private transactions Thirteen minutes later, the picture sharpens. The AI is not just *aligned with* privacy โ€” it is transacting. It would be interesting to see AI making private transactions/payments in different meta/games/real world etc. Agentic payments across games, virtual worlds, and the real world โ€” described in 2022, on a chain that already has the encrypted-balance and SC primitives to support them. ### Decades of experience for current & coming times In December 2022, Captain compresses the entire design philosophy into one sentence. In-addition to above DERO uses decades of experience to make sure DERO offers best privacy possible required in current & coming times. *Decades of experience*, *best privacy possible*, *current & coming times* โ€” the triad Captain returns to whenever someone asks why DERO looks the way it does. The chain is not optimized for today's threat model alone. ### Stargate is the explainable version By April 2023, Stargate is live and people are reading the protocol. Captain wants the record clear about what they are reading. Current DERO Stargate is heavily downgraded so that people can understand it easily. The companion to the 2022 downgrade quote, and arguably the more pointed of the two. Stargate is the version of DERO that fits in a developer's head. There is more behind it. ### Why his heart still doesn't allow SC interactions August 2023. Asked why DERO still does not allow smart contracts to interact with each other, Captain reaches for the same phrase he used eight months earlier. Just for such & similar reasons, My heart doesn't allow SCs interactions. Till current state each & every part has been designed & backed by decades of experience. The second invocation of *decades of experience*, used this time to defend a missing feature rather than a shipped one. The restraint is the design. --- ## Blackbox DERO: The Long-Term Vision A recurring pattern in Captain's public messages is the hint that Stargate โ€” the protocol you can run today โ€” is a deliberately constrained subset of a larger design. The quotes below are the moments where Captain steps furthest forward, sketching a future "entirely blackbox" DERO with no visible TXIDs, no mining-reward visibility, and no explorer. Read these as statements of design intent, not as committed roadmap. The credo is six words: *Before Protocol you need Vision/Future.* What ships at any given moment is the slice of that vision the protocol can carry now. ### HE scope is intentionally limited "for now" Asked why DERO-HE applies homomorphic encryption only to balances and transfers rather than the full state, Captain frames the current scope as a starting point, not a destination. No, DERO is using HE for just balances etc. for now because it more than the enough for the current requirement. Also it will help to learn more. In future this will change based on the requirements and use cases. The first hint that what's shipped is not what's planned โ€” HE coverage is sized to current needs, with explicit room to grow. ### Everything floating in DERO-sea is encrypted Later the same day, Captain restates the invariant in its most poetic form โ€” wallets exist only to prove ownership over data the network itself never sees in cleartext. In DERO-HE user balances/transfers etc. are never decrypted and all logics operate on encrypted data only. Wallets are just required to prove your ownership to the encrypted data. Everyone and everything floating in DERO-sea is encrypted. The always-encrypted invariant, stated as a property of the medium rather than a feature of the wallet. ### CryptoNote is outdated for DERO Minutes later, Captain publicly retires the old privacy stack โ€” not as a value judgement on CryptoNote itself, but as a statement about which protocol family DERO belongs to going forward. DERO has moved beyond outdated CryptoNote Protocol . Not interested in any new developments /improvements/exploits in CryptoNote Protocol. Good if [user] has done some improvements on CryptoNote Protocol but for DERO it is outdated protocol. The moment the old privacy stack is publicly retired โ€” improvements there are someone else's project, not DERO's. ### Obfuscation out, HE in, plaintext never Asked to spell out the substitution, Captain gives the replacement thesis in one paragraph: obfuscation is a workaround, HE is the actual primitive. CryptoNote Protocol is full of obfuscation only. DERO is migrating to Homomorphic Encryption which supports operations/audit etc. on encrypted data only, No need of any plaintext data/balance/TXs calculations. DATA/Balances/TXs will always stay in encrypted state on DERO network and only user/wallet can decrypt balances/data. The contrast is the point: obfuscation hides plaintext that still exists; HE removes the plaintext from the network's view entirely. ### "Most of these projects will be seen running on DERO network" Responding to critics who couldn't see what DERO was building, Captain reframes the disagreement as a vision gap rather than a technical one. Looks these people/DEV seems have no idea what DERO is building and aiming for. Coming times No surprises if most of these projects will be seen running on DERO network. The thesis: if the substrate is right, the applications migrate. Said in 2021, before most of the surface area existed. ### Entirely blackbox DERO Eighteen months later, Captain sketches the endgame explicitly. Ring members go away; so does the explorer, the mining-channel reward visibility, and the very concept of external audit. Also DERO design can also be upgraded to remove concept of ring members entirely. In upgraded design there will no visible TXIDs, no mining rewards visibilty, no fuss in mining channel & no concept of explorer. And of-course no concept of audit etc. Entirely blackbox DERO. ๐Ÿ™‚ This is the anchor the section is named for. Every other quote points at this end-state from a different angle. --- ## Broadcasts & Slogans Captain wrote in compressed declaratives. When he wanted a principle to stick, he stripped it to a single line and let it land as identity rather than argument โ€” the kind of phrasing that doubles as a status message, a channel broadcast, and a community password. The lines below are the recurring anchors: short, repeatable, and structurally identical across years. They are the slogans the network rallied around, in his own words. ### Not your keys, not your coins Dropped into #trading during exchange-listing chatter. The most iconic crypto custody mantra, repeated by Captain across years as a project-level anchor. Not your keys, Not your coins. The canonical self-custody line, stated without elaboration. Captain treated it as load-bearing โ€” the precondition for everything else DERO claimed about privacy. ### Actual decentralized blockchain Answering a question in #technical-questions, Captain reframed the conversation away from feature comparison and toward a binary choice. Welcome to actual decentralized blockchain else pls stay with Central Banking systems. A dichotomy slogan โ€” either you are running an actually decentralized chain or you are inside the system DERO was built to refuse. No middle category. ### Mine on your own node A mining-channel one-liner that fuses three of Captain's recurring positions โ€” solo mining, decentralization, and self-hosting โ€” into a single sentence. Best thing for network security, decentralization is to mine on your own node. Mining policy stated as security policy. The slogan format hides the load-bearing claim: pool mining and network security are not the same goal. ### No heroes, only community Posted into #dero-discussion in response to attempts to lionize individual contributors. Captain rejected the framing outright. There are no HERO/S in decentralized network. Community is the actual guardian in decentralized network. A pure aphorism, and a direct rebuke of personality-cult thinking. The guardian of a decentralized network is, by definition, plural. ### Run your own node Two weeks after the no-heroes line, Captain returned to operational ground. The refined wallet-and-node mantra he repeated in many variations. For best security & privacy, run your own node & connect wallet to your own node. Security and privacy collapsed into one action. The slogan is short enough to fit in a status message and specific enough to function as a configuration instruction. --- ## Biographical Notes Captain rarely talked about himself. When he did, it came in fragments โ€” a sentence about upbringing, a reference to writing compilers decades ago, a note that he was traveling. No timeline, no biography, no resume. What we have is what slipped out around the technical work. Read together, these fragments include a reference to compiler work decades ago, a sentence about upbringing, named acknowledgments of contributors, notes about travel, and the occasional cost admission. We draw no portrait beyond what he wrote. ### Nature, discipline, values January 2018 on Bitcointalk, weeks after the DERO mainnet launch. Someone had offered praise and, implicitly, the suggestion that DERO should chase ICO money like everyone else that cycle. Captain answered with what reads as a personal credo. ...thanks for your words but It depends more on the nature, discipline, values in your life. We will work and build together a strong community slowly our own in hard way. We don't need anything big in millions or so like ICO. We will work hard and produce something & if remarkable DERO will get its success. Thank you. The refusal of ICO money and the framing of character โ€” nature, discipline, values โ€” sets the posture the rest of the archive keeps returning to. "Slowly our own in hard way" is close to a thesis statement for how the project would be run. ### The teacher called Experience July 2018. Serena, a long-time contributor, had left the project after an incident. Captain's first public reply to her after the departure is reconciliatory rather than defensive. No stable per-message permalink survives โ€” only the thread context. Hello @Serena, My first reply to you since you left. I believe you have contributed lots of efforts and time for the DERO Community. Thanks for that. For me you are still the same kind and sweet person. Pls don't allow this incident to affect you any way. Let the good and positive in you be more powerful. I have seen and handle lots of such in life, thanks to the teacher called Experience. You will always have my good wishes. Feel free for anything else. Thanks. Regards. "The teacher called Experience" is the older-mentor register that surfaces throughout the archive. The phrasing โ€” formal, deliberate, slightly archaic โ€” is also a recognizable voice fingerprint. ### Environment and society June 2022 in #random, mid-conversation about beliefs and worldview. This is the closest Captain ever comes to placing himself culturally on the map. Perhaps most of my view/beliefs are due to the enviroment/society I have been raised. One sentence, no elaboration. He never named a country, a language, or a tradition. He attributed his worldview to where he came from and left it there. ### Traveling, meeting friends Mid-December 2022, posted to #dero-discussion. A rare note about being away from the desk. As I am traveling & meeting some friends atm. Would like to say that world is changing/evolving faster than our beliefs. Lots of extra-ordinary achievements in medical,astrophysics & other sciences. I am also surprised to see the developments. Looks coming times will be totally different. He names medical and astrophysics alongside other sciences. He does not elaborate on where he was traveling or whom he was meeting. ### First specialized compilers, two decades back August 2023 in #random, explaining why DVM uses an interpreter instead of a compiler. The aside is the closest Captain comes to dating his own professional origin. That's why DERO has interpreter instead of compiler. Even though team has experience of writing some of the first specialized compilers more than 2 decades back. Compiler work "more than 2 decades back" places the team's systems-engineering roots in the 1990s or earlier โ€” long before crypto. It also fits a pattern that recurs across the archive: we know how to do it the other way, we chose this on purpose. ### Exchange listings, time, and money lost December 11, 2023, in #dero-discussion โ€” a rare cost admission. We lost several $100K & lot's of precious time in this exchange listings. A rare admission of cost โ€” both money and time โ€” from someone who almost never talked about either. --- ## The Trail: Cryptic Clues and Last Words What follows is a curated arc of messages from Captain that, in retrospect, read differently than they did in the moment. Most are short. Several are signoffs. A few are practical announcements where the word choice lands harder than it needed to. The collection opens with his first public Christmas in 2017, then picks up again in his late period from late 2022 through his last message on New Year's Day 2024. Together they trace a shift in voice โ€” from technical build updates to short broadcast greetings โ€” visible in the last stretch before he went MIA in January 2024. This page draws no conclusions about what happened to him. The pattern is the point: certain phrases recur ("tomorrow never comes," "coming times," "rest & peace," "bless"), and the rhythm of his presence changes. Read them as Captain wrote them. The community has continued without him since. ### Tomorrow never comes (Christmas 2017) Captain's first public Christmas message on the original Bitcointalk DERO thread, six months into the project. Signed 'Capt. Dero' โ€” the handle that would stick for seven years. The phrase he opens with here will echo, in different forms, until his final week. Happy Holidays to everyone, Live your life and enjoy it to the fullest. Tomorrow never comes. Be safe and responsible. Capt. Dero. 'Tomorrow never comes' is the anchor phrase of this collection. It appears here on his first public Christmas and bookends a seven-year arc. ### Third person โ€” 'captain's msgs' From #random in September 2022, in a thread about community waiting on his replies. Captain answers in the third person about himself โ€” a register he uses rarely, and almost always when redirecting attention away from his own role. Thats the real issue, why depend/wait for captain's msgs. ๐Ÿ™‚ Sixteen months before the messages stopped, he was already nudging the community to not depend on them. This 'don't wait for me' theme repeats elsewhere in the same period. ### Rest & peace only Two weeks later, in #dero-discussion, someone asked him a question that required a longer answer than he had energy for. He demurred in a way he almost never did. Complex to answer . ATM looking for some rest & peace only. Captain rarely spoke about his own state. This is one of the few times the word 'rest' surfaces in first person. ### Higher level of peace A December 2022 message in #random about wallet-side ring configuration. The technical content is unremarkable; the closing phrase is what makes it sit in this collection. Feel free to optimize/update Rings/wallets etc. This is purely wallet-side & independent of core. Advance users can define their own private logic also in wallet for higher level of peace. The word 'peace' recurs across this period. ### Coming times From #dero-discussion in mid-January 2023, in a conversation about why anyone should care about privacy tech now. Captain's answer reframes the question as a survival skill rather than a feature. Better to start learning more about privacy now. Because in coming times that knowledge will be required anyhow to survive & maintain edge with respect to others. 'Coming times' is the most urgent register Captain uses in this period. The phrase recurs in adjacent messages through 2023. ### Down forever A February 2023 announcement that the hosted browser wallet at wallet.dero.io would be shut down. The substance is operational; the word choice is the part that registers in this list. wallet.dero.io will be down forever in coming weeks. Pls familiarize yourself with cli or Engram wallet. Part of a pattern in this stretch where Captain routes users toward self-sufficient tooling โ€” CLI, Engram, local nodes โ€” over anything he himself hosts. ### Severely disconnected Mid-March 2023, in #dero-discussion. Someone had asked, again, about his periodic disappearances. This is one of the few times he explained them directly. I always travel to parts which are severely disconnected to rest of the world both physically & with network capabilities. All good ,Nothing new. ๐Ÿ™‚ Addressed to the community as a whole, in passing. The line stands out because Captain almost never described his own movements. ### Bless you all New Year's Eve into New Year's Day 2024, in #dero-discussion. A broadcast greeting, addressed to everyone. Very Very Happy New year to everyone. Bless you all. His last message. The seven-year arc that opened with 'Tomorrow never comes' on Christmas 2017 closes here, with 'Bless you all' on New Year's 2024. --- --- title: "Create, Deploy & Use a Smart Contract on DERO | Step-by-Step Tutorial" description: "End-to-end tutorial: write a DVM-BASIC smart contract, deploy it to the DERO blockchain, interact with its functions, and query its state โ€” all from the command line." keywords: ["DERO smart contract tutorial", "deploy smart contract DERO", "DVM-BASIC tutorial", "DERO development", "scinvoke", "installSc", "getsc", "DERO contract deployment", "blockchain development tutorial"] date: "2026-03-02" lastUpdated: "2026-03-02" authors: ["DHEBP"] slug: "create-deploy-use-smart-contract" canonicalUrl: "https://derod.org/dvm/create-deploy-use-smart-contract" tags: ["dvm", "smart-contracts", "tutorial", "deployment", "development"] --- # Create, Deploy & Use a Smart Contract This is a hands-on tutorial that takes you from a blank file to a working smart contract on the DERO blockchain. By the end, you will have written a contract, deployed it, called its functions, and queried its state โ€” all from the command line. > [!NOTE] > **New to DERO contracts?** Read [Smart Contract Fundamentals](/dvm/smart-contract-fundamentals.md) first for the concepts behind everything in this tutorial. --- ## Prerequisites SC download/balance/parameters checks are done on blockchain using daemon port 40402. But sending/SC install/update/balance transfer etc. are done using wallet port 40403 by rpc methods. **Mental model:** **reads โ†’ daemon, writes โ†’ wallet.** Every example below follows that split. Captain's 2021 quote uses testnet ports (`40402`/`40403`); mainnet is `10102`/`10103`. Same logic. You need three things running: | Component | Purpose | Default Port | |-----------|---------|-------------| | **DERO Daemon** (`derod`) | Connects to the blockchain | `10102` (mainnet) | | **DERO Wallet CLI** | Signs and broadcasts transactions | `10103` (mainnet) | | **Some DERO** | Gas fees for deployment and calls | ~0.01 DERO minimum | ### Mainnet ```bash # Terminal 1: Start the daemon ./derod-darwin # or derod-linux, derod-windows.exe # Terminal 2: Start the wallet with RPC enabled ./dero-wallet-cli --rpc-server --rpc-bind=127.0.0.1:10103 --wallet-file=your_wallet.db ``` ### Testnet (Simulator) ```bash # The simulator bundles daemon + wallet in one process ./simulator-darwin # Wallet RPC on port 30000, Daemon RPC on port 20000 ``` Verify everything is running: ```bash # Check daemon curl -s http://127.0.0.1:10102/json_rpc \ -H 'Content-Type: application/json' \ -d '{"jsonrpc":"2.0","id":"1","method":"DERO.GetInfo"}' | python3 -m json.tool | grep topoheight # Check wallet curl -s http://127.0.0.1:10103/json_rpc \ -H 'Content-Type: application/json' \ -d '{"jsonrpc":"2.0","id":"1","method":"GetAddress"}' | python3 -m json.tool | grep address ``` --- ## Step 1: Write the Contract Create a file called `tipjar.bas` with this content: ```basic Function Initialize() Uint64 10 IF EXISTS("owner") THEN GOTO 100 20 STORE("owner", SIGNER()) 30 STORE("totalTips", 0) 40 STORE("tipCount", 0) 50 RETURN 0 100 RETURN 1 End Function Function Tip() Uint64 10 IF DEROVALUE() == 0 THEN GOTO 100 20 STORE("totalTips", LOAD("totalTips") + DEROVALUE()) 30 STORE("tipCount", LOAD("tipCount") + 1) 40 STORE("lastTipper", SIGNER()) 50 RETURN 0 100 RETURN 1 End Function Function Withdraw(amount Uint64) Uint64 10 IF SIGNER() != LOAD("owner") THEN GOTO 100 20 SEND_DERO_TO_ADDRESS(SIGNER(), amount) 30 RETURN 0 100 RETURN 1 End Function Function GetStats() Uint64 10 RETURN LOAD("tipCount") End Function ``` **What each function does:** | Function | Who Can Call | What Happens | |----------|-------------|-------------| | `Initialize` | Deployer (once) | Sets the deployer as owner, initializes counters | | `Tip` | Anyone | Accepts DERO, increments counters, records last tipper | | `Withdraw` | Owner only | Sends DERO from the contract to the owner | | `GetStats` | Anyone | Returns the tip count | > [!WARNING] > **`RETURN 0` = success, `RETURN 1` = failure.** If a function returns 1, all state changes revert and any DERO sent is returned to the caller. --- ## Step 2: Deploy the Contract Deployment uses the wallet's `transfer` RPC method with the contract source in the `sc` field. The wallet accepts the code as **base64**. ```bash # Base64-encode the contract SC_CODE=$(base64 < tipjar.bas) # Deploy curl -s http://127.0.0.1:10103/json_rpc \ -H 'Content-Type: application/json' \ -d "{ \"jsonrpc\": \"2.0\", \"id\": \"1\", \"method\": \"transfer\", \"params\": { \"sc\": \"$SC_CODE\", \"ringsize\": 2 } }" ``` The response contains the **TXID**, which is also the **SCID** (Smart Contract ID): ```json { "jsonrpc": "2.0", "id": "1", "result": { "txid": "a1b2c3d4e5f6..." } } ``` Save this TXID โ€” it's the permanent address of your contract on the blockchain. > [!NOTE] > **SCID = TXID.** On DERO, the smart contract's unique identifier is the hash of the deployment transaction. There is no separate "contract address" concept. ### Deploy with Initialize Parameters If your `Initialize` function accepts parameters, pass them via `sc_rpc`: ```bash curl -s http://127.0.0.1:10103/json_rpc \ -H 'Content-Type: application/json' \ -d "{ \"jsonrpc\": \"2.0\", \"id\": \"1\", \"method\": \"transfer\", \"params\": { \"sc\": \"$SC_CODE\", \"sc_rpc\": [ {\"name\": \"someParam\", \"datatype\": \"S\", \"value\": \"hello\"}, {\"name\": \"someNumber\", \"datatype\": \"U\", \"value\": 42} ], \"ringsize\": 2 } }" ``` Data types: `"S"` = String, `"U"` = Uint64, `"H"` = Hash. --- ## Step 3: Wait for Confirmation DERO blocks are produced roughly every 18 seconds. Wait at least one block before interacting with the contract: ```bash sleep 20 ``` > [!WARNING] > **One TX at a time.** DERO's encrypted balance system only allows one pending (unconfirmed) transaction per wallet. Always wait for a transaction to confirm before sending the next one. Attempting concurrent transactions will cause the second one to be silently dropped. --- ## Step 4: Verify Deployment Query the contract's state using the daemon's `getsc` method: ```bash SCID="your_txid_here" curl -s http://127.0.0.1:10102/json_rpc \ -H 'Content-Type: application/json' \ -d "{ \"jsonrpc\": \"2.0\", \"id\": \"1\", \"method\": \"DERO.GetSC\", \"params\": { \"scid\": \"$SCID\", \"code\": true, \"variables\": true } }" | python3 -m json.tool ``` A successful deployment returns the contract's stored variables: ```json { "result": { "stringkeys": { "C": "46756e6374696f6e20496e69...", "owner": "2f5388721e5efad8...", "totalTips": 0, "tipCount": 0 }, "balance": 0, "status": "OK" } } ``` | Field | Meaning | |-------|---------| | `stringkeys.C` | The contract source code (hex-encoded โ€” recover with `echo "" \| xxd -r -p`) | | `stringkeys.owner` | The raw address of the deployer (whatever your `Initialize` stored) | | `stringkeys.totalTips` | Current total tips (0 after deploy) | | `balances` | Map keyed by SCID. **`0x000...000` is native DERO.** Any other 32-byte key is a token SCID. | | `balance` | Convenience field โ€” same as `balances["0000...0000"]` | If `stringkeys` is missing or empty, the deployment failed โ€” likely a syntax error in the contract or an `Initialize` that returned 1. > [!NOTE] > **Where the shape comes from.** Captain demonstrated this exact `getsc` response in [#dero-he-testnet on 2021-11-28](https://discord.com/channels/419781880632836096/737351309396541471/914341300826963968) โ€” same hex-encoded `C`, same zerohash balance key. The contract Code lives at `dvm/sc.go` (`SC_Code_Key = 'C'`); the balance map convention is in [`cmd/derod/rpc/rpc_dero_getsc.go`](https://github.com/deroproject/derohe/blob/main/cmd/derod/rpc/rpc_dero_getsc.go). ### Query Specific Variables Instead of fetching all variables, you can request specific keys: ```bash curl -s http://127.0.0.1:10102/json_rpc \ -H 'Content-Type: application/json' \ -d "{ \"jsonrpc\": \"2.0\", \"id\": \"1\", \"method\": \"DERO.GetSC\", \"params\": { \"scid\": \"$SCID\", \"keysstring\": [\"totalTips\", \"tipCount\"] } }" | python3 -m json.tool ``` This returns `valuesstring` with the values in the same order as the requested keys. --- ## Step 5: Call a Function (Send a Tip) Use the `scinvoke` method to call contract functions. To send a tip, call `Tip` with some DERO attached: ```bash curl -s http://127.0.0.1:10103/json_rpc \ -H 'Content-Type: application/json' \ -d "{ \"jsonrpc\": \"2.0\", \"id\": \"1\", \"method\": \"scinvoke\", \"params\": { \"scid\": \"$SCID\", \"sc_rpc\": [ {\"name\": \"entrypoint\", \"datatype\": \"S\", \"value\": \"Tip\"} ], \"sc_dero_deposit\": 10000, \"ringsize\": 2 } }" ``` | Parameter | Purpose | |-----------|---------| | `scid` | The contract to call | | `sc_rpc[0].value` | The function name (`"Tip"`) | | `sc_dero_deposit` | DERO to send (in atomic units: 10000 = 0.1 DERO) | | `ringsize` | Must be 2 for functions that use `SIGNER()` | > [!NOTE] > **Atomic units:** 1 DERO = 100,000 atomic units. So `10000` = 0.1 DERO, `100000` = 1 DERO. ### Call a Function with Arguments For functions that take parameters (like `Withdraw`), add them to `sc_rpc`: ```bash curl -s http://127.0.0.1:10103/json_rpc \ -H 'Content-Type: application/json' \ -d "{ \"jsonrpc\": \"2.0\", \"id\": \"1\", \"method\": \"scinvoke\", \"params\": { \"scid\": \"$SCID\", \"sc_rpc\": [ {\"name\": \"entrypoint\", \"datatype\": \"S\", \"value\": \"Withdraw\"}, {\"name\": \"amount\", \"datatype\": \"U\", \"value\": 5000} ], \"ringsize\": 2 } }" ``` --- ## Step 6: Verify the State Changed After waiting for confirmation (~20 seconds), query the state again: ```bash sleep 20 curl -s http://127.0.0.1:10102/json_rpc \ -H 'Content-Type: application/json' \ -d "{ \"jsonrpc\": \"2.0\", \"id\": \"1\", \"method\": \"DERO.GetSC\", \"params\": { \"scid\": \"$SCID\", \"variables\": true } }" | python3 -c " import sys, json data = json.load(sys.stdin) keys = data['result'].get('stringkeys', {}) print('tipCount:', keys.get('tipCount', '?')) print('totalTips:', keys.get('totalTips', '?')) print('balance:', data['result'].get('balance', 0)) " ``` Expected output after one 0.1 DERO tip: ``` tipCount: 1 totalTips: 10000 balance: 10000 ``` --- ## The three-step pattern โ€” minimal reference The TipJar tutorial above shows the full lifecycle. If you just want the smallest possible reference template to copy-paste, this is Captain's original three-step example. **The contract** (`helloworld.bas`): ```basic Function Initialize() Uint64 10 STORE("owner", SIGNER()) 20 RETURN 0 End Function Function Save() Uint64 10 STORE("test", "HELLOWORLD") 20 RETURN 0 End Function ``` **Step 1 โ€” Install via wallet RPC:** ```bash curl --request POST --data-binary @helloworld.bas \ http://127.0.0.1:10103/install_sc ``` The response contains the SCID โ€” use it in the next two steps. **Step 2 โ€” Query state via daemon RPC:** ```bash curl http://127.0.0.1:10102/json_rpc -d '{ "jsonrpc": "2.0", "id": "0", "method": "DERO.GetSC", "params": { "scid": "YOUR_SCID_HERE", "variables": true } }' -H 'Content-Type: application/json' | jq ``` **Step 3 โ€” Call a function via wallet RPC:** ```bash curl http://127.0.0.1:10103/json_rpc -d '{ "jsonrpc": "2.0", "id": "0", "method": "scinvoke", "params": { "sc_dero_deposit": 3, "scid": "YOUR_SCID_HERE", "ringsize": 2, "sc_rpc": [ { "name": "entrypoint", "datatype": "S", "value": "Save" } ] } }' -H 'Content-Type: application/json' | jq -r ".result.txid" ``` > [!NOTE] > **Pattern source.** This three-step flow โ€” `install_sc` (wallet) โ†’ `getsc` (daemon) โ†’ `scinvoke` (wallet) โ€” comes from Captain's `helloworld.bas` walkthrough in [#dero-he-testnet on 2021-11-28](https://discord.com/channels/419781880632836096/737351309396541471/914510084900536350). The original used testnet ports (`40402`/`40403`); the examples above are converted to mainnet (`10102`/`10103`). RPC shapes (`sc_dero_deposit`, `sc_rpc` array, `ringsize`) are unchanged on Release 142 โ€” see [`walletapi/rpcserver/rpc_websocket_server.go:208,319`](https://github.com/deroproject/derohe/blob/main/walletapi/rpcserver/rpc_websocket_server.go) and [`walletapi/rpcserver/rpc_scinvoke.go:28`](https://github.com/deroproject/derohe/blob/main/walletapi/rpcserver/rpc_scinvoke.go). --- ## Complete Workflow Summary ### Write the contract Create a `.bas` file with `Initialize` and your business logic functions. ### Deploy Base64-encode the source and send it via the wallet's `transfer` method with the `sc` field. ### Wait for confirmation At least one block (~18 seconds). Always wait between transactions. ### Verify deployment Query with `DERO.GetSC` โ€” check that `stringkeys` contains your stored variables. ### Interact Call functions with `scinvoke`. Attach DERO with `sc_dero_deposit`. Pass arguments in `sc_rpc`. ### Query state Use `DERO.GetSC` with `variables: true` or targeted `keysstring` queries. --- ## Common Mistakes | Mistake | Symptom | Fix | |---------|---------|-----| | Putting SC_CODE in `sc_rpc` instead of the `sc` field | Contract deploys but has no state (empty `stringkeys`) | Use the top-level `"sc"` parameter โ€” the wallet auto-decodes base64 from this field only | | Sending two transactions without waiting | Second TX silently dropped (TXID returned but never mined) | Wait โ‰ฅ20 seconds between transactions | | Using ringsize > 2 with `SIGNER()` | Function returns 1 (access check fails) | Use `ringsize: 2` for any function that checks `SIGNER()` | | Forgetting `DEROVALUE()` check | Contract accepts 0-value calls as deposits | Always guard with `IF DEROVALUE() == 0 THEN GOTO [fail]` | | Not checking `stringkeys` after deploy | Assuming deploy succeeded when Initialize actually failed | Always verify with `GetSC` โ€” if `stringkeys` is empty, the contract has no state | --- ## What's Next - [DVM-BASIC Language Reference](/dvm/dvm-basic.md) โ€” Full syntax, types, and built-in functions - [DVM Function Reference](/dvm/dero-virtual-machine.md) โ€” Complete function list with gas costs - [Token Contract](/smartContracts/token.md) โ€” Deploy a private fungible token - [Wallet RPC API](/rpc-api/wallet-rpc-api.md) โ€” Full reference for `transfer`, `scinvoke`, and more - [Daemon RPC API](/rpc-api/daemon-rpc-api.md) โ€” Full reference for `GetSC`, `GetTransaction`, and more --- --- title: "DERO Virtual Machine (DVM): Private Smart Contract Platform | DERO Blockchain" description: "Explore the DERO Virtual Machine (DVM), a revolutionary platform for running both public and private smart contracts with enhanced security and privacy on the DERO blockchain." keywords: ["DERO Virtual Machine", "DVM", "private smart contracts", "DVM-BASIC", "blockchain programming", "DERO smart contracts", "secure smart contracts", "privacy blockchain", "decentralized applications", "blockchain development"] date: "2024-08-26" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/dvm.jpeg" slug: "dvm" canonicalUrl: "https://derod.org/dvm/dero-virtual-machine" tags: ["dvm", "smart-contracts", "development", "programming", "dvm-basic", "blockchain"] --- # DERO Virtual Machine (DVM) DERO Virtual Machine represents the entire DERO Smart Contracts eco-system which runs on the DERO blockchain. DVM is a decentralized platform that runs smart contracts: applications that run exactly as programmed without any possibility of downtime, censorship, fraud or third-party interference. DERO's unique innovation is that tokens issued by smart contracts become encrypted balances in user wallets through homomorphic encryption. While contract code and state remain public and auditable, token balances and transfer amounts are completely private. Smart Contracts are nothing but rules which apply on transacting parties. Current version of DVM is an interpreter based system to avoid security vulnerabilities, issues and compiler backdoors. This also allows easy audits of Smart Contracts for quality, bug-testing and security assurances. DVM supports a new language DVM-BASIC. DVM apps run on a from scratch custom built privacy supporting, encrypted blockchain, an enormously powerful shared global infrastructure that can move value around and represent the ownership of assets/property without leaking any information. No one knows who owns what and who transferred to whom. - This enables developers to create puzzles, games, voting, markets, store registries of debts or promises, move funds in accordance with instructions given long in the past (like a will or a futures contract) and many other ideas/things that have not been invented yet, all without a middleman or counterparty risk. - DVM-BASIC is a contract-oriented, high-level language for implementing smart contracts. It is influenced by GW-BASIC, Visual Basic and C and is designed to target the DERO Virtual Machine (DVM). It is very easy to program and very readable. - DVM runs Smart Contracts which are a collection of functions written in DVM-BASIC. These functions can be invoked over the blockchain to do something. Each smart contract is currently self-contained โ€” cross-contract calls are architecturally planned but not yet enabled. - DVM supports a number of comment formats such as ', //, /* */ as good documentation is necessary. # DVM-Basic DVM Example Factorial program ' This is a comment // This comment is supported /* this is multi-line comment */ Function Factorial(s Uint64) Uint64 // this is a comment 10 DIM result,scopy as Uint64 /* this is also comment */ 15 LET scopy = s 20 LET result = 1 30 LET result = result * s 40 LET s = s - 1 50 IF s >= 2 THEN GOTO 30 70 RETURN result End Function - DVM smart contracts are written in a DVM-BASIC custom BASIC style language with line numbers. - DVM supports `uint64` and `string` data types. - DVM interprets the smart contract and processes it line by line. - `uint64` supports almost all operators, namely `+`, `-`, `*`, `/`, `%`. - `uint64` supports the following bitwise operators: `&`, `|`, `^`, `!`, `>>`, `<<`. - `uint64` supports the following logical operators: `>`, `>=`, `<`, `<=`, `==`, `!=`. - `string` supports only the `+` operator. It supports concatenation with a `uint64`. - `string` supports `==` and `!=` logical operators. - All DVM variables are mandatory to define and are initialized to default values, namely `0` and an empty string (`""`). ### Smart Contract Execution Guidelines - Smart Contract execution must return 0 to persist any changes made during execution. No panics should occur during execution. ### DERO Smart Contract Examples - [Launching your token/asset on DERO blockchain](https://github.com/deroproject/documentation/blob/master/DVMDOCS/examples/token/token_sc_guide.md) - [Launching your exchange for interchanging tokens/assets](https://github.com/deroproject/documentation/tree/master/DVMDOCS/examples/assetexchange) - [DERO Smart Contract Examples](https://github.com/deroproject/documentation/tree/master/DVMDOCS/examples) - [More Examples](https://forum.dero.io/t/darch-decentralized-architecture-competition-series/1318) ### DERO Default Ports **Mainnet:** - Mining Getwork Port: `10100` TCP - P2P Default Port: `10101` UDP - RPC Default Port: `10102` TCP - Wallet RPC Default Port: `10103` TCP **Testnet:** - P2P Default Port: `40401` - RPC Default Port: `40402` - Wallet RPC Default Port: `40403` *NB: Change ports to mainnet or testnet based on your requirements.* ### Statements Supported by DERO Virtual Machine - DIM - FUNCTION - GOTO - IF - LET - RETURN #### DIM - DIM stands for data in memory and is used to define variable names within a function. Syntax: ```basic 10 DIM variable1 as type 20 DIM variable1, variable2 as type 30 DIM key, owner as String 40 DIM count as Uint64 ``` Supported types in DVM are Uint64 and String. All DVM variables are mandatory to be defined and are initialized to default values: 0 for Uint64 and "" for String. #### FUNCTION - Function statement is used to define a function. Syntax: ```basic Function ADD(x Uint64, y Uint64) Uint64 10 RETURN x + y End Function ``` ### Function Syntax Function syntax can be of two types: 1. `Function function_name(0 or more arguments)` 2. `Function function_name(0 or more arguments) return type` #### DVM Function Rules - All functions start with the `Function` keyword. - Function names should be alphanumeric. - If the first letter of the function is an uppercase alphabet, the function is exported and can be invoked externally via blockchain transactions. - If the first letter of the function is a lowercase alphabet, the function can only be invoked by other functions within the smart contract. - Functions may or may not have a return type. - All functions must use `RETURN` to return from the function or to return a value. `RETURN` is mandatory. - All functions must end with `End Function`. `End Function` is mandatory. - A function can have an implicit parameter value of type `uint64`, which contains the amount of DERO value sent with the transaction. - Any error during processing will immediately stop execution and discard all changes that occur during SC execution. - Any entrypoint which returns a `uint64` value of 0 is termed as success and will make the transaction commit all state changes. #### Specific Function Commands - **`GOTO`**: Used to jump to any line number within the function. It cannot cross function boundaries. Syntax: ```basic // If signer is owner then withdraw. Function Withdraw(amount Uint64) Uint64 10 IF LOAD("owner") == SIGNER() THEN GOTO 30 20 RETURN 1 30 SEND_DERO_TO_ADDRESS(SIGNER(), amount) 40 RETURN 0 End Function ``` - **`IF`**: Executes a statement if a specified condition is true. It has two forms. Syntax: ```basic 10 IF COUNT == 0 THEN GOTO 110 20 IF COUNT == 0 THEN GOTO 110 ELSE GOTO 200 ``` - **`LET`**: Used to assign a value to a variable. Value can be as complex as possible and can contain complex expressions. Syntax: ```basic 10 LET COUNT = 10 20 LET x = 2 + 3 + ADD(2, 3) ``` - **`RETURN`**: Used to return from a function. It has two forms. Syntax: ```basic 10 RETURN 0 20 RETURN X + Y ``` Return value must match the type defined while declaring the function. `RETURN` can be used anywhere within a function. #### DVM Inbuilt Support Functions DVM includes support functions that provide specific functionality or expose DVM internals. ### Support Functions #### `VERSION(v String)` - **Description:** Sets a version to `dvm.VERSION`. Returns 1 if successful, panics otherwise. - **Return Type:** Uint64 - **ComputeCost:** 1000 - **StorageCost:** 0 #### `LOAD(variable)` - **Description:** Loads a variable previously stored in the blockchain using STORE function. Return type depends on what is stored. It panics if the value does NOT exist. - **Return Type:** Uint64/String (depending on what is stored) - **ComputeCost:** 5000 - **StorageCost:** 0 - **Syntax:** ```basic 10 IF LOAD(name) != SIGNER() THEN GOTO 30 ``` #### `EXISTS(variable)` - **Description:** Returns 1 if the variable is stored in the database via STORE and 0 otherwise. - **Return Type:** Uint64 - **ComputeCost:** 5000 - **StorageCost:** 0 - **Syntax:** ```basic 10 IF EXISTS(name) THEN GOTO 50 ``` #### `STORE(key variable, value variable)` - **Description:** Stores key and value in the database. All storage state of the smart contract is accessible only from the smart contract which created it. Returns 1. - **Return Type:** Uint64 - **ComputeCost:** 10000 - **StorageCost:** 0 - **Syntax:** ```basic 10 STORE("owner", SIGNER()) // Store in DB ["owner"] = address ``` #### `DELETE(variable)` - **Description:** Sets the rawkey value to `[]byte{}` effectively deleting it from storage. Returns 1. - **Return Type:** Uint64 - **ComputeCost:** 3000 - **StorageCost:** 0 #### `MAPEXISTS(variable)` - **Description:** Returns 1 if the variable has been stored in RAM (current invoke session) via MAPSTORE and 0 otherwise. - **Return Type:** Uint64 - **ComputeCost:** 1000 - **StorageCost:** 0 #### `MAPGET(variable)` - **Description:** Loads a variable previously stored in RAM (current invoke session) via MAPSTORE. Return type depends on what is stored. It panics if the value does NOT exist. - **Return Type:** Uint64/String (depending on what is stored) - **ComputeCost:** 1000 - **StorageCost:** 0 #### `MAPSTORE(key variable, value variable)` - **Description:** Stores key and value in RAM (current invoke session). All MAPSTORE state is accessible only from the session in which it is stored. Returns 1. - **Return Type:** Uint64 - **ComputeCost:** 1000 - **StorageCost:** 0 #### `MAPDELETE(variable)` - **Description:** Deletes the element from the map in RAM (current invoke session). If the key does not exist, delete has no action. Returns 1. - **Return Type:** Uint64 - **ComputeCost:** 1000 - **StorageCost:** 0 #### `RANDOM(limit Uint64)` - **Description:** RANDOM returns a random number using a PRNG seeded on BLID, SCID, TXID. The first form gives a uint64, the second form returns a random number in the range 0 - (limit), 0 is inclusive, limit is exclusive. - **Return Type:** Uint64 - **ComputeCost:** 2500 - **StorageCost:** 0 - **Syntax:** ```basic 10 LET winner = RANDOM() % deposit_count // Finding winner. ``` #### `SCID()` - **Description:** Returns SMART CONTRACT ID which is currently running. - **Return Type:** String - **ComputeCost:** 2000 - **StorageCost:** 0 #### `BLID()` - **Description:** Returns current BLOCK ID which contains the current execution-in-progress TXID. - **Return Type:** String - **ComputeCost:** 2000 - **StorageCost:** 0 #### `TXID()` - **Description:** Returns current TXID which is execution-in-progress. - **Return Type:** String - **ComputeCost:** 2000 - **StorageCost:** 0 #### `DERO()` - **Description:** Returns a string representation of zerohash which is of type crypto.Hash. - **Return Type:** String - **ComputeCost:** 10000 - **StorageCost:** 0 #### `BLOCK_HEIGHT()` - **Description:** Returns current chain height of BLID(). - **Return Type:** Uint64 - **ComputeCost:** 2000 - **StorageCost:** 0 #### `BLOCK_TIMESTAMP()` - **Description:** Returns current timestamp of BLID(). - **Return Type:** Uint64 - **ComputeCost:** 2500 - **StorageCost:** 0 #### `SIGNER()` - **Description:** Returns the address of who signed/sent this transaction. Ringsize of tx must be 2 for this value to be known or else empty. SIGNER() returns the raw address. - **Return Type:** String - **ComputeCost:** 5000 - **StorageCost:** 0 - **Syntax:** ```basic 10 IF LOAD("owner") == SIGNER() THEN GOTO 30 ``` #### `UPDATE_SC_CODE(sc_code String)` - **Description:** Stores updated SC code of type string. If it is not of type string, return 0, else return 1. - **Return Type:** Uint64 - **ComputeCost:** 5000 - **StorageCost:** 0 #### `IS_ADDRESS_VALID(address String)` - **Description:** Returns 1 if address is valid, 0 otherwise. - **Return Type:** Uint64 - **ComputeCost:** 50000 - **StorageCost:** 0 #### `ADDRESS_RAW(address String)` - **Description:** Returns address in RAW form as 33 byte keys, stripping away textual/presentation form. Two addresses should always be compared in RAW form. - **Return Type:** String - **ComputeCost:** 60000 - **StorageCost:** 0 #### `ADDRESS_STRING(p String)` - **Description:** Returns address in STRING form. If it can be evaluated, a string form of an address will be returned, otherwise, return an empty string. - **Return Type:** String - **ComputeCost:** 50000 - **StorageCost:** 0 #### `SEND_DERO_TO_ADDRESS(a String, amount Uint64)` - **Description:** Sends amount DERO from SC DERO balance to an address which should be in raw form. Address must be in string DERO/DETO form. If the SC does not have enough balance, it will panic. - **Return Type:** Uint64 - **ComputeCost:** 70000 - **StorageCost:** 0 #### `SEND_ASSET_TO_ADDRESS(a String, amount Uint64, asset String)` - **Description:** Sends amount ASSET from SC ASSET balance to an address which should be in raw form. Address must be in string DERO/DETO form. If the SC does not have enough balance, it will panic. - **Return Type:** Uint64 - **ComputeCost:** 90000 - **StorageCost:** 0 #### `DEROVALUE()` - **Description:** Gets the amount of DERO sent within this transaction. - **Return Type:** Uint64 - **ComputeCost:** 10000 - **StorageCost:** 0 #### `ASSETVALUE(asset String)` - **Description:** Gets the amount of a given ASSET sent within this transaction. - **Return Type:** Uint64 - **ComputeCost:** 10000 - **StorageCost:** 0 #### `ATOI(s String)` - **Description:** Returns a Uint64 representation of a string. Else, panic. - **Return Type:** Uint64 - **ComputeCost:** 5000 - **StorageCost:** 0 #### `ITOA(n Uint64)` - **Description:** Returns string representation of a Uint64. Else, panic. - **Return Type:** String - **ComputeCost:** 5000 - **StorageCost:** 0 #### `SHA256(s String)` - **Description:** Returns a string sha2-256 hash of a given string. Else, panic. - **Return Type:** String - **ComputeCost:** 25000 - **StorageCost:** 0 #### `SHA3256(s String)` - **Description:** Returns a string sha3-256 hash of a given string. Else, panic. - **Return Type:** String - **ComputeCost:** 25000 - **StorageCost:** 0 #### `KECCAK256(s String)` - **Description:** Returns a string sha3-keccak256 hash of a given string. Else, panic. - **Return Type:** String - **ComputeCost:** 25000 - **StorageCost:** 0 #### `HEX(s String)` - **Description:** Returns a hex encoded string value of a given string. Else, panic. - **Return Type:** String - **ComputeCost:** 10000 - **StorageCost:** 0 #### `HEXDECODE(s String)` - **Description:** Returns a hex decoded string value of a given hex string. Else, panic. - **Return Type:** String - **ComputeCost:** 10000 - **StorageCost:** 0 #### `MIN(f Uint64, s Uint64)` - **Description:** Returns the minimum value of 2 Uint64 values. Else, panic. - **Return Type:** Uint64 - **ComputeCost:** 5000 - **StorageCost:** 0 #### `MAX(f Uint64, s Uint64)` - **Description:** Returns the maximum value of 2 Uint64 values. Else, panic. - **Return Type:** Uint64 - **ComputeCost:** 5000 - **StorageCost:** 0 #### `STRLEN(s String)` - **Description:** Returns the length of a given string in Uint64. Else, panic. - **Return Type:** Uint64 - **ComputeCost:** 20000 - **StorageCost:** 0 #### `SUBSTR(s String, offset Uint64, length Uint64)` - **Description:** Returns the substring of a given string with offset and length defined. Else, panic. - **Return Type:** String - **ComputeCost:** 20000 - **StorageCost:** 0 #### `PANIC` - **Description:** Panics. - **Return Type:** Panic - **ComputeCost:** 10000 - **StorageCost:** 0 More about DVM-Basic here: [Explaining DVM-Basic](/dvm/dvm-basic.md) --- ### Execution Limits & Constraints The DVM enforces hard limits to ensure deterministic execution and prevent abuse. Exceeding any of these causes the contract call to panic and revert. | Limit | Value | Source | |-------|-------|--------| | **Interpreted lines per call** | 2,000 | `dvm/dvm.go` `LIMIT_interpreted_lines` | | **Expression evaluations per call** | 11,000 | `dvm/dvm.go` `LIMIT_evals` | | **Compute gas per call** | 10,000,000 | `dvm/sc.go` `GasComputeLimit` | | **Max storage gas per TX** | 20,000 atomic units | `config/config.go` `MAX_STORAGE_GAS_ATOMIC_UNITS` | | **String concatenation** | 1 MiB total | Panics if `len(a) + len(b) >= 1,048,576` | | **Line numbers** | 1 to 2^64 โˆ’ 2 | 0 and `MaxUint64` are invalid | | **Line number order** | Strictly ascending | Duplicate or out-of-order lines are rejected at parse time | | **Nested functions** | Not allowed | Parser rejects `Function` inside another function | > [!WARNING] > **The 2,000-line and 11,000-eval limits are per function call, not per contract.** A contract can have many functions, but each individual invocation must complete within these bounds. Design complex logic across multiple calls rather than one monolithic function. --- ## Related Pages **Learn the Language:** - [DVM-BASIC Programming Guide](/dvm/dvm-basic.md) - Complete language reference - [Smart Contract Examples](/smartContracts/token.md) - Full code examples **Privacy Features:** - [Private Smart Contracts](/privacy/private-smart-contracts.md) - How contract privacy works - [Homomorphic Encryption](/privacy/homomorphic-encryption.md) - Encrypted state storage **Build & Deploy:** - [Token Contract Tutorial](/smartContracts/token.md) - Step-by-step guide - [Wallet RPC API](/rpc-api/wallet-rpc-api.md) - Deploy via RPC - [Daemon RPC API](/rpc-api/daemon-rpc-api.md) - Query contract state **Technical Details:** - [Golang Performance](/features/golang.md) - Why DVM is fast - [DERO Tokens](/basics/tokens.md) - Understanding asset transfers --- --- title: "DVM-BASIC: DERO's Smart Contract Language Guide | DERO Blockchain" description: "Comprehensive guide to DVM-BASIC, DERO's smart contract programming language with syntax, examples, and best practices for blockchain developers." keywords: ["DVM-BASIC", "DERO programming", "blockchain language", "smart contract code", "DERO development", "privacy smart contracts", "blockchain programming", "DVM language", "BASIC blockchain", "DERO smart contracts"] date: "2024-08-26" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/dvm-basic.jpeg" slug: "dvm-basic" canonicalUrl: "https://derod.org/dvm/dvm-basic" tags: ["dvm", "programming", "development", "smart-contracts", "tutorial", "language"] --- # DVM-BASIC Programming Guide DVM-BASIC is DERO's smart contract programming language - a blockchain-optimized BASIC variant that's easy to learn yet powerful enough for complex dApps with privacy features. **Source:** `dvm/` - Virtual Machine implementation ## Language Features - Line-numbered syntax (like GW-BASIC) - Strong typing: `Uint64` and `String` - Built-in blockchain functions - Privacy-preserving operations - Deterministic execution ## Quick Start ```basic Function Initialize() Uint64 10 STORE("owner", SIGNER()) 20 STORE("counter", 0) 30 RETURN 0 End Function Function Increment() Uint64 10 DIM current as Uint64 20 LET current = LOAD("counter") 30 STORE("counter", current + 1) 40 RETURN 0 End Function ``` ## Authorization patterns `SIGNER()` returns the wallet address that sent the current transaction โ€” Captain's words: *"may not be the owner of the SC."* It coincides with the owner during `Initialize` (canonical pattern below) but on every other call you must check explicitly. If your contract has no stored-owner gate, anyone can call `UpdateCode` and overwrite your logic โ€” the DVM does not gate `UpdateCode` at the protocol level. SIGNER() -> its the wallet adress which is sending this TX. It may not be the owner of the SC. Please install owner address in DB during SC install. If you have no owner stored & verification anyone can update your SC. The canonical pattern: store the owner during `Initialize`, then gate every privileged function with `IF LOAD("owner") == SIGNER() THEN ...`. ```basic Function Initialize() Uint64 10 STORE("owner", SIGNER()) 20 RETURN 0 End Function Function UpdateOwner(new_owner String) Uint64 10 IF LOAD("owner") == SIGNER() THEN GOTO 30 20 RETURN 1 30 STORE("owner", ADDRESS_RAW(new_owner)) 40 RETURN 0 End Function ``` Without line 10, anyone can call `UpdateOwner` and seize the contract. ## Data Types & Variables | Type | Range | Default | Usage | |------|-------|---------|-------| | `Uint64` | 0 to 18,446,744,073,709,551,615 | `0` | Numbers, balances, counts | | `String` | Variable (size limits apply) | `""` | Text, addresses, keys | **Declare variables:** ```basic 10 DIM counter as Uint64 20 DIM name, symbol as String ``` ## Operators | Type | Operators | |------|-----------| | **Arithmetic** | `+` `-` `*` `/` `%` | | **Bitwise** | `&` `\|` `^` `!` `>>` `<<` | | **Comparison** | `>` `>=` `<` `<=` `==` `!=` | | **String** | `+` (concat), `==`, `!=` | ## Control Flow **IF-THEN-ELSE:** ```basic 10 IF value > 100 THEN GOTO 30 ELSE GOTO 50 ``` **Loops with GOTO:** ```basic 10 LET counter = 0 20 LET counter = counter + 1 30 IF counter < 10 THEN GOTO 20 ``` ## Comments ```basic ' Single-line comment // Alternative single-line /* Multi-line comment */ ``` ## Functions **Syntax:** ```basic Function Name(param1 Type, param2 Type) ReturnType 10 RETURN value End Function ``` **Visibility:** - **Uppercase** first letter โ†’ Public (callable externally) - **Lowercase** first letter โ†’ Private (internal only) **Return values:** - `0` = success - Non-zero = error code ## Blockchain Functions ### State Management | Function | Purpose | |----------|---------| | `STORE(key, value)` | Save to blockchain state | | `LOAD(key)` | Read from blockchain state | | `EXISTS(key)` | Check if key exists | ### Identity & Transaction | Function | Purpose | |----------|---------| | `SIGNER()` | Get transaction sender address | | `TXID()` | Get current transaction ID | | `ADDRESS_RAW(string)` | Convert address string to raw format | | `IS_ADDRESS_VALID(string)` | Validate address format | ### Asset Operations | Function | Purpose | |----------|---------| | `SEND_DERO_TO_ADDRESS(addr, amount)` | Transfer DERO | | `SEND_ASSET_TO_ADDRESS(addr, amount, scid)` | Transfer asset/token | | `DEROVALUE()` | Get DERO sent in transaction | | `ASSETVALUE(scid)` | Get asset sent in transaction | ### Blockchain Info | Function | Purpose | |----------|---------| | `BLOCK_HEIGHT()` | Current block height | | `BLOCK_TIMESTAMP()` | Current block timestamp | | `SCID()` | This contract's ID | ### Cryptographic | Function | Purpose | |----------|---------| | `SHA256(data)` | Compute SHA256 hash | | `KECCAK256(data)` | Compute Keccak256 hash | ## Best Practices 1. **Security** - Always validate inputs and permissions 2. **Gas efficiency** - Minimize STORE/LOAD operations 3. **Line spacing** - Use increments of 10 for future insertions 4. **Error codes** - Return meaningful error codes 5. **Testing** - Use Simulator before deployment ## Example: Token Contract ```basic Function Initialize() Uint64 10 STORE("owner", SIGNER()) 20 STORE("supply", 1000000) 30 STORE("balance:" + SIGNER(), 1000000) 40 RETURN 0 End Function Function Transfer(to String, amount Uint64) Uint64 10 DIM sender as String 20 DIM sender_bal, recipient_bal as Uint64 30 LET sender = SIGNER() 40 IF IS_ADDRESS_VALID(to) != 1 THEN GOTO 200 50 IF amount <= 0 THEN GOTO 200 60 LET sender_bal = LOAD("balance:" + sender) 70 IF sender_bal < amount THEN GOTO 200 80 IF EXISTS("balance:" + ADDRESS_RAW(to)) THEN GOTO 100 90 STORE("balance:" + ADDRESS_RAW(to), 0) 100 LET recipient_bal = LOAD("balance:" + ADDRESS_RAW(to)) 110 STORE("balance:" + sender, sender_bal - amount) 120 STORE("balance:" + ADDRESS_RAW(to), recipient_bal + amount) 130 RETURN 0 200 RETURN 1 ' Error End Function Function BalanceOf(address String) Uint64 10 IF EXISTS("balance:" + ADDRESS_RAW(address)) THEN GOTO 30 20 RETURN 0 30 RETURN LOAD("balance:" + ADDRESS_RAW(address)) End Function ``` ## Learn More - [DERO Virtual Machine](/dvm/dero-virtual-machine.md) - DVM architecture - [Token Contract Tutorial](/smartContracts/token.md) - Build a full token - [Smart Contract Examples](/smartContracts/assets.md) - More examples **Tip:** The DVM-BASIC language evolves with DERO. Check official docs for updates! --- ## Related Pages **Smart Contract Examples:** - [Token Contract](/smartContracts/token.md) - Build a private token - [Assets Exchange](/smartContracts/assets.md) - Token swap contract - [Lottery Contract](/smartContracts/lottery.md) - Decentralized lottery - [Name Service](/smartContracts/name.md) - Register usernames **Understanding the DVM:** - [DERO Virtual Machine](/dvm/dero-virtual-machine.md) - DVM architecture - [Private Smart Contracts](/privacy/private-smart-contracts.md) - Contract privacy features **Deploy & Test:** - [Wallet RPC API](/rpc-api/wallet-rpc-api.md) - Deploy contracts programmatically - [Running a Node](/basics/running-a-node.md) - Setup testnet for development --- --- title: "Smart Contract Fundamentals: Understanding DERO Contracts | DERO Blockchain" description: "Learn what DERO smart contracts actually are, how they execute on-chain, why DVM-BASIC was chosen over Solidity, and the core patterns that make contracts secure and auditable." keywords: ["DERO smart contracts", "DVM-BASIC", "blockchain programming", "smart contract security", "DERO vs Ethereum", "on-chain execution", "state machine", "DERO development", "blockchain fundamentals", "contract deployment"] date: "2026-02-17" lastUpdated: "2026-02-17" authors: ["DHEBP"] image: "/assets/dvm.jpeg" slug: "smart-contract-fundamentals" canonicalUrl: "https://derod.org/dvm/smart-contract-fundamentals" tags: ["dvm", "smart-contracts", "fundamentals", "development", "security", "dvm-basic"] --- # Smart Contract Fundamentals Before diving into syntax or examples, it helps to understand what a DERO smart contract actually *is*, how it runs, and why DERO chose a radically different approach from other chains. --- ## What Is a Smart Contract? At its core, a DERO smart contract is a **program that lives on the blockchain and controls money**. When you deploy one, the source code gets stored on every node in the DERO network. When someone calls a function on that contract, every node runs the same code and arrives at the same result. That consensus is what makes it trustless โ€” no single party can cheat. Think of it as a **state machine with a bank account**: | Component | What It Does | |-----------|-------------| | **Storage** | Key-value pairs that persist on-chain (the contract's "database") | | **Balance** | The contract can hold and send DERO | | **Functions** | Entry points that anyone can call | | **Rules** | Logic that determines who can do what and when | Every interaction with a smart contract follows the same pattern: someone sends a transaction that says *"call function X with these arguments"*, the network executes it, and the result either commits or reverts. --- ## Why DVM-BASIC? Most chains use Solidity (Ethereum), Rust (Solana), or Move (Aptos). DERO chose a BASIC dialect called **DVM-BASIC** โ€” and that's a deliberate decision, not a limitation. | Design Goal | How DVM-BASIC Achieves It | |-------------|--------------------------| | **Auditability** | BASIC is one of the simplest languages ever created. Anyone can read a contract and understand what it does, even non-programmers. On a privacy chain where trust matters, readability is a feature. | | **Deterministic Execution** | No floating point, no complex memory model, no recursion traps. Every operation produces the same result on every node. This is critical for consensus. | | **Small Attack Surface** | Solidity's complexity has led to billions in exploits (reentrancy, overflow, delegatecall). DVM-BASIC doesn't support the patterns that create those vulnerabilities. | | **Source = Bytecode** | Unlike Ethereum where you deploy compiled bytecode (and must separately verify source), DERO stores and executes the actual source code. What you deploy is what runs. What anyone reads on-chain with `getsc` is the actual executing code. | > [!NOTE] > **What you deploy is what runs.** There is no compiler step, no bytecode translation, no room for compiler backdoors. The source code *is* the program. Anyone can inspect it on-chain at any time. --- ## The Line Number System This is often the most visually unfamiliar part for newcomers: ```basic Function Initialize() Uint64 10 STORE("owner", SIGNER()) 20 STORE("treasury", 0) 30 RETURN 0 200 RETURN 1 End Function ``` **Line numbers are the control flow mechanism.** There are no `if/else` blocks, no `while` loops, no `try/catch`. Instead, you have `GOTO` โ€” jump to a specific line number. This is how BASIC has always worked since the 1960s. - Lines `10, 20, 30...` execute sequentially - `GOTO 200` jumps to line 200 (typically an error/failure return) - The gap between numbers (10, 20, 30 instead of 1, 2, 3) is intentional โ€” it leaves room to insert lines later without renumbering - `RETURN 0` means success, `RETURN 1` means failure This looks primitive, but it's **by design**. There is no hidden control flow. You can trace every possible execution path by following the line numbers. An auditor can verify a contract in minutes. --- ## `Initialize` vs `InitializePrivate` Every contract has exactly one initializer that runs **once**, at install time. It is named **either** `Initialize` **or** `InitializePrivate` โ€” and which name you choose is the *only* difference between the two contract types DERO recognizes. ```basic // Type 0 โ€” "Open" contract Function Initialize() Uint64 10 STORE("owner", SIGNER()) 20 RETURN 0 End Function // Type 1 โ€” "Private" contract: identical body, different name Function InitializePrivate() Uint64 10 STORE("owner", SIGNER()) 20 RETURN 0 End Function ``` At deploy, the daemon checks the function name and sets a single metadata byte: ```go // blockchain/transaction_execute.go:325-326 if _, ok := sc.Functions["InitializePrivate"]; ok { meta.Type = 1 // present -> Private (Type 1); absent -> Open (Type 0) } // ...then the matching name is used as the install entrypoint: // transaction_execute.go:336-337 if meta.Type == 1 { entrypoint = "InitializePrivate" } ``` That byte is the whole distinction: ```go // dvm/sc.go:38 Type byte // 0 = Open, 1 = Private ``` > [!WARNING] > **`InitializePrivate` does NOT hide your contract.** It does not encrypt code, does not encrypt state, and does not change how `STORE`/`LOAD` or `DERO.GetSC` behave. For **both** types the contract code is public and every stored variable is world-readable โ€” `DERO.GetSC` serves Type 0 and Type 1 state identically, with no privacy gate. So what is "private" about a private smart contract? **The tokens it issues**, not the contract itself. When a contract sends an asset with `SEND_ASSET_TO_ADDRESS`, that balance lands **encrypted in the recipient's wallet** and moves wallet-to-wallet with homomorphic encryption afterward โ€” the contract never tracks who holds what. The Type 1 marker is what tells the chain to treat the contract as a private-asset issuer. (See [Private Smart Contracts](/privacy/private-smart-contracts.md) for the token model in full.) **Practical guidance:** if your contract issues tokens/assets, use `InitializePrivate`. If it is a pure logic or storage contract, either name works โ€” but never rely on either one to keep state secret. Anything that must be confidential has to be encrypted by your app **before** it is stored on-chain. --- ## The Core Primitives Everything in DVM-BASIC is built from a handful of building blocks: ### Storage: `STORE` and `LOAD` The contract's persistent memory. These write to and read from on-chain state that survives between calls. ```basic 10 STORE("owner", SIGNER()) // Write to state 20 IF LOAD("owner") == SIGNER() THEN GOTO 40 // Read from state 30 RETURN 1 ``` Every `STORE` modifies the global blockchain state (and costs gas). Every `LOAD` reads what was previously stored. This is the contract's database. ### Identity: `SIGNER()` Returns the address of whoever is calling the function right now. This is how access control works: ```basic 10 IF SIGNER() != LOAD("owner") THEN GOTO 100 ``` *"If the person calling this isn't the owner, reject."* The blockchain cryptographically guarantees that `SIGNER()` is authentic โ€” it cannot be faked. > [!WARNING] > `SIGNER()` requires a ring size of 2. If the transaction uses a higher ring size, `SIGNER()` returns empty. Functions that check `SIGNER()` cannot be called anonymously. ### Receiving Value: `DEROVALUE()` Returns how much DERO was sent along with this function call: ```basic 10 IF DEROVALUE() == 0 THEN GOTO 100 // Reject if no DERO sent 20 STORE("balance", LOAD("balance") + DEROVALUE()) 30 RETURN 0 100 RETURN 1 ``` When someone calls a function and includes DERO, it goes into the contract's balance automatically. `DEROVALUE()` tells the code how much arrived. ### Sending Value: `SEND_DERO_TO_ADDRESS` The contract sends DERO from its own balance to someone: ```basic 10 SEND_DERO_TO_ADDRESS(LOAD("recipient"), amount) 20 RETURN 0 ``` This is the money moving. It happens atomically โ€” either the entire function succeeds (RETURN 0) or everything reverts. ### Address Handling: `ADDRESS_RAW` Converts a human-readable DERO address into the raw format used internally: ```basic 10 STORE("admin", ADDRESS_RAW(adminAddress)) ``` Two addresses should always be compared in raw form. Textual representations can vary, but raw format is canonical. ### Time: `BLOCK_HEIGHT()` Returns the current block number. Used for time-based logic: ```basic 10 IF BLOCK_HEIGHT() < LOAD("unlockHeight") THEN GOTO 100 ``` Since DERO produces blocks roughly every 18 seconds, you can calculate approximate durations. For example, `BLOCK_HEIGHT() + 200` is roughly one hour in the future. --- ## The Execution Model When someone calls a function on a contract, here is what actually happens: ### Transaction Submitted The caller's wallet signs a transaction that says *"call function X on contract Y with these arguments and this much DERO attached."* ### Transaction Enters the DAG DERO uses a block-DAG (not a linear chain), so the transaction gets included in a block. ### Every Node Executes Each node in the network runs the function independently and verifies the result matches. ### State Commits or Reverts If the function returns `0` (success), all `STORE` operations take effect. If it returns `1` (failure), nothing changes โ€” the entire execution is rolled back. ### Consensus Confirms Once enough nodes agree on the result, the state change is finalized. This is why the return value matters so much: | Return Value | Meaning | State Changes | |-------------|---------|---------------| | `RETURN 0` | Success | All `STORE` operations commit | | `RETURN 1` | Failure | Everything reverts โ€” as if the function was never called | It is an all-or-nothing atomic operation. There is no partial state change. --- ## The Security Model DERO smart contracts rely on two fundamental checks that together form the entire security model: ### State Guards Every function checks the contract's current state before acting: ```basic // Only allow withdrawal if status is 1 10 IF LOAD("status") != 1 THEN GOTO 100 ``` This prevents functions from being called at the wrong time or in the wrong order. ### Access Guards Every function checks *who* is calling: ```basic // Only the owner can call this 10 IF SIGNER() != LOAD("owner") THEN GOTO 100 ``` This prevents unauthorized users from calling privileged functions. **Combine both** for robust security: ```basic Function Withdraw(amount Uint64) Uint64 10 IF SIGNER() != LOAD("owner") THEN GOTO 100 // Access guard 20 IF LOAD("locked") == 1 THEN GOTO 100 // State guard 30 SEND_DERO_TO_ADDRESS(SIGNER(), amount) 40 RETURN 0 100 RETURN 1 End Function ``` These two checks โ€” **who is calling** and **is the contract in the right state** โ€” are sufficient to secure any contract logic. --- ## How DERO Contracts Differ from Ethereum | Aspect | Ethereum / Solidity | DERO / DVM-BASIC | |--------|-------------------|-----------------| | **Language** | Solidity (complex, C-like) | DVM-BASIC (simple, line numbers) | | **Deployed As** | Compiled bytecode | Raw source code | | **Privacy** | All state and transactions public | Homomorphic encryption on transactions | | **Contract Calls** | Contracts can call other contracts (composability) | Contracts are currently isolated (cross-contract calls are architecturally planned but not yet enabled) | | **Reentrancy Risk** | Major attack vector | Impossible โ€” no external calls during execution | | **Token Storage** | Balances stored in contract mapping | Balances stored encrypted in user wallets | | **Upgradability** | Proxy patterns (complex) | Optional via `UPDATE_SC_CODE()` (simpler than proxy patterns) | | **Gas Model** | Dynamic gas market | Simpler fee structure | The **isolation** point is worth understanding: DERO contracts are currently self-contained. The DVM architecture includes the internal infrastructure for cross-contract calls (the `Shared_State` structure supports it), but this capability is not yet enabled. Today, each contract executes independently. This eliminates an entire class of exploits (reentrancy, flash loans, composability attacks) while the DVM matures. Cross-contract composability is a design goal for the future. > [!NOTE] > **Tokens in wallets, not contracts.** On Ethereum, your token balance lives inside a contract's storage (the contract *controls* your tokens). On DERO, tokens are sent to your wallet as encrypted balances. Once issued, the contract cannot freeze, seize, or track them. See [DERO Tokens](/basics/tokens.md) for details. --- ## Putting It All Together Here is a complete minimal contract that demonstrates every core concept โ€” storage, access control, receiving DERO, sending DERO, and state management: ```basic // Tip Jar: anyone can deposit, only the owner can withdraw Function Initialize() Uint64 10 IF EXISTS("owner") THEN GOTO 100 20 STORE("owner", SIGNER()) 30 STORE("totalTips", 0) 40 RETURN 0 100 RETURN 1 End Function Function Deposit() Uint64 10 IF DEROVALUE() == 0 THEN GOTO 100 20 STORE("totalTips", LOAD("totalTips") + DEROVALUE()) 30 RETURN 0 100 RETURN 1 End Function Function Withdraw(amount Uint64) Uint64 10 IF SIGNER() != LOAD("owner") THEN GOTO 100 20 SEND_DERO_TO_ADDRESS(SIGNER(), amount) 30 STORE("totalTips", LOAD("totalTips") - amount) 40 RETURN 0 100 RETURN 1 End Function ``` This is 20 lines of code that creates a trustless payment system: anyone can send tips, only the owner can withdraw, and every operation is verified by the entire network. --- ## What's Next Now that you understand the fundamentals, explore the language and examples: **Learn the Language:** - [DVM-BASIC Programming Guide](/dvm/dvm-basic.md) โ€” Full syntax, types, operators, and best practices - [DVM Function Reference](/dvm/dero-virtual-machine.md) โ€” Complete list of built-in functions with costs **Study Real Contracts:** - [Token Contract](/smartContracts/token.md) โ€” Build a private fungible token - [Assets Exchange](/smartContracts/assets.md) โ€” Token swap mechanics - [Lottery Contract](/smartContracts/lottery.md) โ€” Random selection and payouts - [Name Service](/smartContracts/name.md) โ€” On-chain username registration **Deploy and Test:** - [Wallet RPC API](/rpc-api/wallet-rpc-api.md) โ€” Deploy contracts via RPC - [Daemon RPC API](/rpc-api/daemon-rpc-api.md) โ€” Query contract state with `getsc` --- ## Related Pages **Understanding the Platform:** - [DERO Tokens](/basics/tokens.md) โ€” How token storage and privacy work - [Private Smart Contracts](/privacy/private-smart-contracts.md) โ€” Contract privacy features - [Homomorphic Encryption](/privacy/homomorphic-encryption.md) โ€” Encrypted state and balances **Building Contracts:** - [DVM-BASIC Guide](/dvm/dvm-basic.md) โ€” Language reference and best practices - [DVM Function Reference](/dvm/dero-virtual-machine.md) โ€” Built-in functions and gas costs - [Token Smart Contract](/smartContracts/token.md) โ€” Complete deployment tutorial **Infrastructure:** - [Running a Node](/basics/running-a-node.md) โ€” Set up a testnet for development - [Wallet RPC API](/rpc-api/wallet-rpc-api.md) โ€” Programmatic deployment and invocation --- --- title: "Engram: Decentralized Application Platform for DERO | DERO Blockchain" description: "Explore Engram, a desktop application for accessing and interacting with decentralized applications on the DERO blockchain with enhanced privacy and security features." keywords: ["Engram", "DERO dApp platform", "decentralized applications", "blockchain desktop app", "crypto dApp browser", "DERO Engram", "private dApps", "blockchain privacy", "DERO ecosystem", "TELA applications"] date: "2024-08-26" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/engram-hero.jpeg" slug: "engram" canonicalUrl: "https://derod.org/engram" tags: ["engram", "dapp", "platform", "blockchain", "desktop", "privacy"] --- # What is Engram? ![What is a Engram](/assets/engram_header.png) Engram is a desktop application that serves as a gateway to decentralized applications (dApps) on the DERO blockchain. It provides a secure, privacy-focused environment where users can browse and interact with applications whose code and data reside entirely on the blockchain through smart contracts. Unlike traditional browsers that connect to centralized servers, Engram communicates directly with the DERO network, significantly enhancing user privacy and security. As a compliant host application for TELA content, Engram retrieves application code from the blockchain, verifies its integrity, and executes it in a sandboxed environment. This approach eliminates reliance on centralized infrastructure and protects users from potential surveillance or tampering. > [!NOTE] > Engram connects directly to the DERO blockchain network, allowing users to access decentralized applications without intermediaries or centralized servers. ## Key Benefits Engram offers several advantages over traditional application platforms: **Privacy Protection**: Engram doesn't collect user data or include tracking mechanisms. All interactions occur directly with the blockchain, preventing surveillance by third parties. **Enhanced Security**: Applications run in sandboxed environments with strict permission controls. Code verification ensures applications match their on-chain records, protecting users from malicious modifications. **User-Friendly Interface**: The platform features an intuitive design that simplifies interaction with blockchain applications. Users can easily discover, browse, and use dApps through a clean, familiar interface. **Developer Support**: Engram provides a standardized environment for dApp developers with consistent runtime behavior, local testing tools, and specialized APIs for blockchain interaction. ## Use Cases Engram supports a wide range of decentralized applications: * Privacy-focused social applications for messaging and networking * Financial tools for asset management and token exchanges * Digital ownership platforms for NFTs and collectibles * On-chain games with provable fairness mechanisms * Collaborative tools for document sharing and version control * Educational content with permanent, tamper-proof storage ## Relationship with TELA TELA and Engram work together to deliver a complete decentralized application ecosystem. TELA provides the framework for deploying applications to the blockchain, while Engram serves as the interface through which users access these applications. This partnership establishes common standards for application structure and behavior while keeping all code and data on-chain. The combination creates a truly decentralized application experience where neither the application code nor the platform accessing it relies on centralized infrastructure, maximizing both security and privacy for users. ## Getting Started Ready to explore DERO's decentralized application ecosystem? - [Download Engram](https://github.com/DEROFDN/Engram/releases) - Get the latest version - [Learn about Engram's features](/engram/features.md) - [User guide and tutorials](/engram/user-guide.md) - [Connect your wallet](/engram/wallet-integration.md) - [Explore available dApps](/engram/hosting-dapps.md) - [Developer documentation](https://tela.derod.org/tela-development-guide) --- --- title: "Engram Features: Key Capabilities of the DERO dApp Platform | DERO Blockchain" description: "Explore the key features of Engram, a desktop application for accessing decentralized applications on the DERO blockchain with enhanced privacy and security." keywords: ["Engram features", "DERO dApp platform", "blockchain desktop app", "privacy-first design", "TELA applications", "blockchain security"] date: "2024-08-26" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/engram-features.jpeg" slug: "engram/features" canonicalUrl: "https://derod.org/engram/features" tags: ["engram", "features", "dapp", "platform", "privacy", "security"] --- # Engram Features Engram combines privacy, security, and usability features to create a comprehensive platform for accessing decentralized applications on the DERO blockchain. The platform is designed to protect user data while providing a seamless experience for both users and developers. ## Privacy-First Design Privacy is a foundational principle of Engram's architecture. The platform operates without any tracking or telemetry systems, ensuring that no user data or usage metrics are collected. All application code runs locally without remote dependencies, eliminating potential data leakage through network connections. Engram connects directly to the DERO blockchain network, bypassing intermediary servers that could monitor or manipulate traffic. For applications that need access to sensitive information, Engram implements granular permission controls that give users complete authority over what data each application can access. ## Enhanced Security Security in Engram is implemented through multiple protective layers. Applications run in sandboxed execution environments that isolate them from your system, preventing unauthorized access to local resources. Before execution, all application code is verified against blockchain records to ensure integrity. The platform uses a permission-based access model where applications must request explicit authorization for sensitive operations. This puts users in control of their security boundaries. Additionally, any local data stored by applications is encrypted to protect it from unauthorized access. > [!NOTE] > Applications in Engram operate in isolated contexts with explicit permission requirements, significantly reducing security risks compared to traditional web applications. ## User Interface Engram features a clean, modern interface designed for intuitive navigation. The UI includes dedicated sections for application discovery, where users can browse and search for available dApps on the DERO blockchain. To improve efficiency, the platform maintains lists of favorites and recently accessed applications. The responsive layout adapts to different screen sizes, optimizing the experience across desktop and laptop configurations. ## Technical Capabilities ### TELA Integration As a compliant host application for TELA content, Engram includes comprehensive support for the TELA framework: * TELA-INDEX-1 parser for loading applications deployed via the TELA standard * TELA-DOC-1 renderer for displaying application code from multiple contracts * Efficient application caching to improve performance * Support for shared libraries across multiple applications ### Wallet Connectivity Engram connects to DERO wallets through the XSWD protocol, enabling: * Secure, encrypted communication with your wallet * Transaction signing requests with clear authorization prompts * Balance checking directly within applications * Support for multiple addresses across different applications ### Developer Tools For application developers, Engram provides a suite of tools to streamline development: * Debugging utilities for troubleshooting application behavior * Local testing environment for pre-deployment verification * Network inspection tools to monitor blockchain interactions * Console access for viewing application logs and messages ## Additional Features ### Application Management Engram includes robust application management tools that allow users to: * Update applications to the latest versions or roll back to previous versions if needed * View and contribute to community ratings for applications * Monitor and manage application permissions through a centralized dashboard ### Offline Support The platform functions even with intermittent connectivity through: * Offline mode for accessing previously loaded applications * Background synchronization when connectivity is restored * Caching of content to reduce dependency on constant blockchain connectivity ### Customization Options Users can personalize their experience with: * Theme selection between light and dark modes * Layout configuration to match workflow preferences * Connection settings for optimizing network performance * Default application assignments for specific functions These features combine to make Engram a powerful yet user-friendly platform for the growing ecosystem of decentralized applications on DERO. --- --- title: "Hosting dApps with Engram: Guide to DERO Decentralized Applications | DERO Blockchain" description: "Learn how to discover, browse, and interact with decentralized applications on the DERO blockchain using the Engram platform." keywords: ["Engram dApps", "DERO decentralized applications", "blockchain apps", "TELA applications", "dApp discovery", "Engram app store"] date: "2024-08-26" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/engram-dapps.jpeg" slug: "engram/hosting-dapps" canonicalUrl: "https://derod.org/engram/hosting-dapps" tags: ["engram", "dapps", "applications", "blockchain", "hosting", "discovery"] --- # Hosting and Discovering dApps with Engram Engram serves as a gateway to decentralized applications (dApps) built on the DERO blockchain. This guide explains how to discover, browse, and interact with these applications. ## Understanding DERO dApps Decentralized applications on DERO have several unique characteristics: - **On-chain storage**: Application code is stored directly on the blockchain - **Local execution**: Applications run in your local environment, not on remote servers - **Privacy-preserving**: Built on DERO's private blockchain technology - **TELA standard**: Follow the TELA decentralized web standard for consistency > [!NOTE] > All dApps available through Engram are built using the TELA standard, ensuring a consistent and secure user experience. ## Discovering Applications Engram provides multiple ways to discover dApps: ### Manual SCID Entry If you know the SCID (Smart Contract ID) of an application: 1. Click **Apps** > **Add by SCID** 2. Enter the SCID in the provided field 3. Click **Load Application** 4. Review the application information 5. Click **Add to Library** to save it ## Application Details Each application listing includes important information: - **Name and Description**: What the application does - **Developer**: Who created the application - **Rating**: Community feedback on quality - **Last Updated**: When the application was last modified - **Version**: Current application version - **Permissions**: What the application can access ## Managing Your Application Library ### Adding Applications To add an application to your library: 1. Find the application in the directory 2. Click the **Add to Library** button 3. Review and approve any required permissions 4. The application will appear in your personal library ### Organizing Applications Keep your library organized with these features: - **Favorites**: Star applications for quick access - **Categories**: Create custom categories for organization - **Search**: Quickly find applications by name or function - **Sort options**: Arrange by name, date added, or frequency of use ## Using Applications ### Launching Applications To launch an application: 1. Find the application in your library 2. Click the application tile or the **Launch** button 3. The application will load in the main Engram window 4. Wait for initialization to complete ### Application Permissions Applications may request certain permissions: - **Wallet Access**: Connecting to your DERO wallet - **Storage**: Saving data locally - **Network**: Connecting to external resources - **Notifications**: Sending you alerts > [!WARNING] > Always review permission requests carefully. Only grant permissions that are necessary for the application's functionality. ## Creating Your Own dApps If you're interested in developing applications for Engram: 1. Learn the TELA standard for decentralized web applications 2. Develop your application using HTML, JavaScript, and CSS 3. Deploy your application on the DERO blockchain 4. Share your application's SCID for others to discover For detailed development instructions, see the [TELA Development Guide](https://tela.derod.org/tela-development-guide) and [TELA Documentation](https://tela.derod.org). ## Application Ratings and Reviews ### Rating System Engram uses a community-based rating system: - **Ratings**: Applications can be rated from 0-99 - **First digit**: Represents overall quality category (0-9) - **Second digit**: Provides specific details about the rating (0-9) For example: - 80: Very good - 77: Good, Works well - 43: Should be improved, Bugs - 07: Do not use, Corrupted ### Submitting Ratings To rate an application: 1. Launch the application in Engram 2. Click the **Rate** button in the application menu 3. Choose your rating value 4. Optionally add a comment 5. Submit your rating > [!NOTE] > Each DERO address can submit one rating per application. You can update your rating at any time. ## Security Considerations When using dApps, keep these security practices in mind: - **Verify applications**: Check community ratings and reviews - **Review permissions**: Only grant necessary permissions - **Check SCIDs**: Verify application SCIDs match official sources - **Use separate wallets**: Consider using different wallets for different applications - **Report issues**: Submit feedback for suspicious applications ## Offline Access Engram allows you to access applications even when offline: 1. Applications are cached locally after first use 2. Launch Engram even without internet connectivity 3. Previously used applications will be available 4. Blockchain interactions will resume when connectivity is restored ## Future of DERO dApps The DERO dApp ecosystem is continuously evolving: - **Growing library**: New applications are regularly added - **Enhanced functionality**: Existing applications are improved over time - **Developer tools**: Better development resources are being created - **Community involvement**: User feedback shapes the ecosystem Stay updated by regularly checking the Engram application directory for new additions and updates. --- --- title: "Engram User Guide: How to Use the DERO dApp Platform | DERO Blockchain" description: "Learn how to use Engram, the desktop application for accessing and interacting with decentralized applications on the DERO blockchain." keywords: ["Engram user guide", "DERO dApp platform", "how to use Engram", "blockchain app tutorial", "TELA applications", "DERO wallet connection"] date: "2024-08-26" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/engram-user-guide.jpeg" slug: "engram/user-guide" canonicalUrl: "https://derod.org/engram/user-guide" tags: ["engram", "guide", "tutorial", "dapp", "blockchain", "user"] --- # Engram User Guide This guide will help you navigate and use Engram effectively to access decentralized applications on the DERO blockchain. ## Getting Started After [downloading Engram from GitHub](https://github.com/DEROFDN/Engram/releases), launch the application from your desktop or applications folder. ## Connecting to a DERO Node Before using any applications, you'll need to connect to a DERO node: ### Local Node If you're running a local DERO node: 1. Go to **Settings** > **Node Configuration** 2. Select **Local Node** 3. Enter `127.0.0.1:10102` for mainnet or `127.0.0.1:40402` for testnet 4. Click **Connect** ### Remote Node To connect to your own remote node: 1. Go to **Settings** > **Node Configuration** 2. Select **Remote Node** 3. Enter the node address and port 4. Provide authentication details if required 5. Click **Connect** ### Public Node To use a predefined public node: 1. Go to **Settings** > **Node Configuration** 2. Select **Public Node** 3. Choose a node from the dropdown list 4. Click **Connect** > [!WARNING] > Using public nodes may reduce privacy. For maximum privacy, consider running your own node. ## Connecting Your Wallet To interact with dApps that require wallet functionality: 1. Go to **Wallet** > **Connect Wallet** 2. Choose your connection method: - **XSWD Protocol**: Connect to a wallet supporting XSWD (recommended) - **Manual Connection**: Enter your wallet's connection details 3. Authorize the connection in your wallet application 4. Verify the connection status in the status bar For detailed instructions, see the [Wallet Integration guide](/engram/wallet-integration.md). ## Discovering Applications Engram provides several ways to discover dApps: ### Featured Applications The home screen displays featured and popular applications. Click on any application card to view more details or launch the application. ### Application Directory To browse all available applications: 1. Click **Apps** in the navigation bar 2. Use the category filters to narrow your search 3. Sort by popularity, rating, or recency 4. Click on an application to view its details ### Manual Entry If you know the SCID (Smart Contract ID) of an application: 1. Click **Apps** > **Add Application** 2. Enter the SCID in the input field 3. Click **Load Application** 4. Verify and confirm the application details ## Using Applications ### Launching an Application To launch an application: 1. Find the application in your library or directory 2. Click the **Launch** button 3. The application will open in the main Engram window ### Application Permissions When an application requests permissions: 1. Review the requested permissions carefully 2. Choose to allow or deny each permission 3. Optionally select "Remember my choice" for future use > [!NOTE] > You can review and modify application permissions at any time in **Settings** > **Application Permissions**. ### Interacting with Blockchain When an application needs to interact with the blockchain: 1. The application will request authorization through your connected wallet 2. Review the transaction details carefully 3. Approve or reject the transaction in your wallet 4. Wait for confirmation from the blockchain ## Managing Your Applications ### Favorites To mark an application as a favorite: 1. Navigate to the application details 2. Click the star icon next to the application name 3. The application will appear in your **Favorites** list for quick access ### Updating Applications Engram automatically checks for application updates: 1. When updates are available, you'll see a notification badge 2. Go to **Apps** > **Updates Available** 3. Review the changes in each update 4. Click **Update** to apply the latest version ### Removing Applications To remove an application from your library: 1. Navigate to the application details 2. Click **โ‹ฎ** (more options) 3. Select **Remove from Library** 4. Confirm the removal > [!NOTE] > Removing an application only removes it from your local library. The application remains on the blockchain and can be re-added later. ## Customizing Engram ### Appearance To customize the application appearance: 1. Go to **Settings** > **Appearance** 2. Choose between light and dark themes 3. Adjust the application scaling if needed 4. Configure other visual preferences ### Privacy Settings To adjust your privacy settings: 1. Go to **Settings** > **Privacy** 2. Configure application permission defaults 3. Manage local data storage options 4. Set wallet connection preferences ## Troubleshooting ### Connection Issues If you're having trouble connecting to a node: 1. Verify the node address and port are correct 2. Check that your firewall isn't blocking the connection 3. Try an alternative node temporarily 4. Restart Engram and try connecting again ### Application Loading Problems If an application fails to load: 1. Check your connection to the DERO node 2. Verify the SCID is correct 3. Try clearing the application cache in **Settings** > **Advanced** > **Clear Cache** 4. Restart Engram and try again ### Wallet Connection Issues If you're having trouble connecting your wallet: 1. Ensure your wallet supports the XSWD protocol 2. Verify your wallet is running and unlocked 3. Check network connectivity between Engram and your wallet 4. Try restarting both Engram and your wallet ## Advanced Features ### Developer Mode If you're a developer testing applications: 1. Go to **Settings** > **Advanced** 2. Enable **Developer Mode** 3. Access additional tools through the **Developer** menu ### Console Access To view application logs and debug information: 1. With Developer Mode enabled, press `Ctrl+Shift+I` (or `Cmd+Option+I` on macOS) 2. The developer console will open with logs and errors 3. Use the **Console** tab to interact with the application ## Next Steps Now that you're familiar with using Engram: - [Explore available dApps](/engram/hosting-dapps.md) - [Learn about wallet integration](/engram/wallet-integration.md) - [Discover how to develop TELA applications](https://tela.derod.org/tela-development-guide) --- --- title: "Engram Wallet Integration: Connecting Your DERO Wallet | DERO Blockchain" description: "Learn how to connect your DERO wallet to Engram for seamless interaction with decentralized applications on the DERO blockchain." keywords: ["Engram wallet integration", "DERO wallet connection", "XSWD protocol", "blockchain wallet", "dApp wallet integration", "DERO applications"] date: "2024-08-26" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/engram-wallet.jpeg" slug: "engram/wallet-integration" canonicalUrl: "https://derod.org/engram/wallet-integration" tags: ["engram", "wallet", "integration", "xswd", "dapp", "blockchain"] --- # Wallet Integration with Engram Connecting your DERO wallet to Engram allows you to interact with decentralized applications that require blockchain transactions. This guide explains the integration process and available options. ## Understanding XSWD Protocol Engram uses the XSWD (Cross-Site WebSocket DERO) protocol for secure wallet communication: > [!NOTE] > **Learn About XSWD**: This guide uses the [XSWD protocol](/tools/xswd.md) for wallet communication. See the protocol page for technical details and how XSWD provides secure, permissioned access to your wallet. > [!NOTE] > XSWD enables permissioned web socket interactions between applications and DERO wallets, allowing for secure transactions while maintaining control over your funds. The protocol provides several key benefits: - **Secure connection**: All communication is encrypted - **Permissioned access**: You control what applications can do - **No private key exposure**: Your wallet's private keys never leave your wallet - **Transaction verification**: All transactions require explicit approval ## Compatible Wallets Engram works with wallets that support the XSWD protocol: - [DERO WebSocket Wallet](https://github.com/DEROFDN/xswd) - [Engram Wallet](https://github.com/DEROFDN/Engram-Wallet) - [Other third-party wallets with XSWD support] ## Connection Methods ### XSWD Connection ### Connecting via XSWD (Recommended) This is the preferred method for connecting your wallet to Engram: 1. Ensure your XSWD-compatible wallet is running 2. In Engram, go to **Wallet** > **Connect Wallet** 3. Select **XSWD Connection** 4. Engram will automatically detect available wallets 5. Select your wallet from the list 6. Approve the connection request in your wallet 7. You'll see a confirmation message in Engram when connected ### Manual Connection ### Manual Connection If automatic detection doesn't work, you can manually connect: 1. In your wallet, find your XSWD connection details (typically in settings) 2. Note the connection address (usually `127.0.0.1:PORT`) 3. In Engram, go to **Wallet** > **Connect Wallet** 4. Select **Manual Connection** 5. Enter the connection address 6. Click **Connect** 7. Approve the connection request in your wallet 8. You'll see a confirmation message when connected ## Wallet Permissions When connecting your wallet, Engram will request certain permissions: ### Basic Permissions - **View Balance**: See your DERO balance - **View Addresses**: Access your wallet addresses - **Network Information**: See blockchain status ### Extended Permissions (Optional) - **Create Transactions**: Generate unsigned transactions - **Sign Transactions**: Authorize and sign transactions - **Deploy Smart Contracts**: Create new contracts on the blockchain > [!WARNING] > Always review permission requests carefully. Only grant permissions that you're comfortable with. ## Managing Wallet Connections ### Viewing Connection Status To check your wallet connection status: 1. Look for the wallet icon in the status bar - Green: Connected and ready - Yellow: Connected with limited permissions - Red: Not connected or connection issues 2. Hover over the icon for more details ### Disconnecting Your Wallet To disconnect your wallet from Engram: 1. Go to **Wallet** > **Disconnect Wallet** 2. Confirm the disconnection 3. The wallet status icon will update to show you're disconnected ### Changing Connected Wallet To switch to a different wallet: 1. First disconnect your current wallet 2. Go to **Wallet** > **Connect Wallet** 3. Select the new wallet to connect 4. Follow the standard connection process ## Using Your Wallet with dApps ### Transaction Approval When using a dApp that requires blockchain transactions: 1. The application will create a transaction request 2. Engram will forward this request to your connected wallet 3. Your wallet will display the transaction details for review 4. Review the details carefully before approving 5. Approve or reject the transaction in your wallet 6. The result will be sent back to the application ### Viewing Transaction History To see your transaction history: 1. Go to **Wallet** > **Transaction History** 2. View a list of all transactions made through Engram 3. Click on any transaction for more details 4. Filter transactions by application, type, or status ## Security Considerations ### Best Practices Follow these security best practices when connecting your wallet: - **Verify applications**: Only connect to trusted dApps - **Check transaction details**: Always review transactions before approval - **Use session timeouts**: Configure your wallet to disconnect after inactivity - **Separate wallets**: Consider using different wallets for different purposes - **Regular updates**: Keep both Engram and your wallet software updated ### Privacy Settings Enhance your privacy with these settings: 1. Go to **Settings** > **Privacy** 2. Enable **Request Confirmation for All Transactions** 3. Configure **Wallet Connection Timeout** 4. Set **Default Permission Level** to your preference ## Troubleshooting Wallet Connections ### Common Issues #### Wallet Not Detected If Engram doesn't detect your wallet: 1. Ensure your wallet is running and unlocked 2. Verify the wallet supports XSWD protocol 3. Check that no firewall is blocking communication 4. Try the manual connection method #### Connection Timeouts If the connection times out: 1. Verify your wallet is still running 2. Check network settings on both applications 3. Restart both Engram and your wallet 4. Try using a different port for connection #### Transaction Failures If transactions fail: 1. Check your wallet has sufficient balance 2. Verify your network connection is stable 3. Ensure your wallet is properly synchronized with the blockchain 4. Try creating a simple test transaction ## Advanced Wallet Features ### Multi-Wallet Support Engram supports connecting multiple wallets simultaneously: 1. Go to **Wallet** > **Manage Wallets** 2. Click **Add Wallet** 3. Follow the connection process for each wallet 4. Choose which wallet to use for each application ### Hardware Wallet Integration For hardware wallet users: 1. Connect your hardware wallet to your computer 2. Use an XSWD-compatible wallet as a bridge 3. Connect the bridge wallet to Engram 4. Transactions will be forwarded to your hardware wallet for approval ## Next Steps Now that your wallet is connected: - [Explore available dApps](/engram/hosting-dapps.md) - [Learn how to use Engram](/engram/user-guide.md) - [Understand XSWD Protocol](/tools/xswd.md) - Technical details of the connection protocol **For Developers:** - [Wallet RPC API](/rpc-api/wallet-rpc-api.md) - Available wallet methods - [TELA Development](https://tela.derod.org/tela-development-guide) - Build XSWD-enabled apps - [Complete XSWD API](https://tela.derod.org/xswd/overview) - Full protocol reference --- --- title: "AstroBWT: DERO's CPU-Friendly Mining Algorithm | DERO Blockchain" description: "Discover DERO's innovative AstroBWT mining algorithm that ensures fair mining by preventing specialized hardware advantages through Burrows-Wheeler Transform technology." keywords: ["AstroBWT", "Burrows-Wheeler Transform", "DERO mining", "ASIC resistance", "CPU mining", "cryptocurrency mining", "decentralized mining", "mining algorithm", "fair mining", "blockchain mining"] date: "2024-08-26" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/AstroBWT.jpg" slug: "astroBWT" canonicalUrl: "https://derod.org/features/astroBWT" tags: ["features", "mining", "AstroBWT", "CPU", "algorithm"] --- # AstroBWT ![AstroBWT](/assets/AstroBWT.jpg) AstroBWT introduces a novel approach to cryptocurrency mining, specifically designed to thwart specialized mining hardware like ASICs, FPGAs, and GPUs. What sets this algorithm apart from conventional CPU-based crypto mining is its foundation in mathematical proofs. At its core, AstroBWT employs the Burrows-Wheeler Transform (BWT), a complex data rearrangement technique rooted in Information Theory and Compression Domains. AstroBWT distinguishes itself from numerous existing algorithms that adhere to pre-defined computational paths by incorporating the BWT, a domain of study with a history of rigorous research spanning more than three decades. Despite notable efforts by technology giants like Intel and NVIDIA to create optimized BWT versions, these implementations have not yet demonstrated a significant advantage over CPUs in mining. CPUs are typically preferred in mining contexts because of their wide availability and versatility across various mining algorithms and tasks. AstroBWT serves as a convergence point between cryptography, computational theory, and practical applications. Its success holds the promise of not just revolutionizing mining technology but also influencing scientific innovation across various fields. ## Scientific Impacts Beyond cryptocurrency, optimized AstroBWT could revolutionize domains like Bioinformatics and DNA Sequencing. A more efficient BWT algorithm could lead to groundbreaking advancements in scientific research. Learn more: [Mining Guide - Start mining with AstroBWT](/basics/mining.md) --- --- title: "Bulletproofs: DERO's Advanced Zero-Knowledge Proofs | DERO Blockchain" description: "Explore DERO Rocket Bulletproofs, a groundbreaking implementation that enables transaction privacy with verification 10X faster than other cryptocurrencies, without revealing underlying data." keywords: ["DERO Rocket Bulletproofs", "zero-knowledge proofs", "privacy blockchain", "cryptographic verification", "confidential transactions", "transaction privacy", "blockchain privacy", "cryptographic tools", "trustless verification", "secure transactions"] date: "2024-08-26" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/bulletproofs.jpeg" slug: "bulletproofs" canonicalUrl: "https://derod.org/features/bulletproofs" tags: ["features", "bulletproofs", "zero-knowledge", "privacy", "cryptography"] --- # What are Bulletproofs? ![Rocket Bulletproofs](/assets/bulletproofs.jpeg) Bulletproofs serve as cryptographic tools that offer a way to verify the existence of information without revealing the actual content. For instance, they can ascertain that a number falls within a certain range while keeping the specifics of that number private. Unlike zk-SNARKs, which demand a trusted setup, Bulletproofs enable trustless verification, enhancing privacy within transactions. The primary function of Bulletproofs extends beyond enabling confidential transactions; they also significantly reduce the size of verification proofs, often condensing them to around 10% of their original size. This reduction not only ensures smaller transactions but also reinforces privacy measures. ## DERO Rocket Bulletproofs Introduced in June 2018, DERO made a pioneering move by deploying Rocket Bulletproofs on its mainnet, marking a significant milestone as one of the first cryptocurrencies to adopt this advancement. DERO's Bulletproofs were crafted from the ground up, not borrowed or adapted from any existing public implementations. This independent development resulted in a highly optimized implementation with **exceptional performance** - approximately 10X faster than typical bulletproof implementations. DERO's Rocket Bulletproofs were built specifically for DERO's unique architecture, showcasing custom cryptographic engineering. These bulletproofs are celebrated for their exceptional speed, robust security, and scalability, setting a high bar for privacy technology performance. --- --- title: "DERO Virtual Machine: Smart Contract Execution Platform | DERO Blockchain" description: "Explore the DERO Virtual Machine (DVM), a powerful execution environment for private and public smart contracts written in DVM Basic language on the DERO blockchain." keywords: ["DERO Virtual Machine", "DVM", "smart contracts", "DVM Basic", "decentralized applications", "blockchain programming", "DERO smart contracts", "private smart contracts", "blockchain development", "cryptocurrency applications"] date: "2024-08-26" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/dvm.jpg" slug: "dvm" canonicalUrl: "https://derod.org/features/dvm" tags: ["features", "DVM", "smart-contracts", "virtual-machine", "development"] --- # Dero Virtual Machine (DVM) ![Dero Virtual Machine](/assets/dvm.jpg) The Dero Virtual Machine (DVM) is a critical component within the DERO blockchain ecosystem. It serves as the execution environment for DERO smart contracts. Similar to other blockchain virtual machines (such as Ethereum's EVM), the DVM enables the deployment and execution of decentralized applications (dApps) by processing smart contracts written in DVM Basic, a custom BASIC-style language specific to DERO. DVM serves as the execution environment for smart contracts, enabling developers to build decentralized applications on the DERO blockchain while ensuring security, consistency, and interoperability within the network. ## Dero Virtual Machine Features ### Smart Contract Execution The DVM executes smart contracts written in DVM Basic, allowing users to deploy and execute decentralized applications on the DERO blockchain. ### DVM Basic Language Smart contracts are written in DVM Basic, a custom BASIC-style language that resembles traditional BASIC but tailored for blockchain-based operations, featuring line numbers, basic arithmetic, conditionals, and storage manipulation. ### State Management The DVM manages the state changes of the blockchain through smart contract execution, including updating data in the blockchain, managing tokens, and executing logic according to predefined rules. ### Security It ensures secure and consistent execution of smart contracts by providing deterministic behavior across all nodes in the network. ### Blockchain Operations The DVM interacts with the blockchain's consensus algorithm and verifies transactions, ensuring that the code is executed correctly and the state changes are applied uniformly across the network. More about DVM-Basic here: [Explaining DVM-Basic](/dvm/dvm-basic.md) --- --- title: "TLS-Encrypted P2P Network | DERO Blockchain" description: "DERO's TLS-over-UDP network architecture provides encrypted communication, preventing eavesdropping and tampering while maintaining performance." keywords: ["TLS encryption", "UDP network", "blockchain security", "DERO network", "encrypted P2P", "network privacy", "secure communication", "P2P encryption"] date: "2024-08-26" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/encrypted_network.jpeg" slug: "encrypted-network" canonicalUrl: "https://derod.org/features/encrypted-network" tags: ["features", "privacy", "TLS", "network", "P2P"] --- # TLS-Encrypted P2P Network ![Encrypted Network](/assets/encrypted_network.jpeg) DERO is the first blockchain to use **TLS-encrypted UDP** for all P2P network communication, protecting against eavesdropping and tampering while maintaining high performance. > [!NOTE] > **Innovation:** Self-signed TLS certificates over KCP/UDP provide privacy without certificate authorities or trusted third parties. --- ## Why Network Encryption Matters **Without encryption (Bitcoin, Ethereum):** ``` Network observer (ISP, government) can see: โœ“ Who you're connecting to โœ“ Transaction broadcasts (plaintext) โœ“ Block propagation timing โœ“ Network metadata patterns Privacy: Zero ``` **With TLS encryption (DERO):** ``` Network observer sees: โœ“ Encrypted packets โœ— Cannot read contents โœ— Cannot identify transaction types โœ— Cannot tamper with data Privacy: Network-level protection ``` --- ## DERO's Network Architecture ### TLS over KCP/UDP ```mermaid graph LR D1[DERO Node 1] --> KCP[KCP Protocol
UDP-based] KCP --> TLS[TLS Layer
Self-signed certs] TLS --> NET[Network] NET --> TLS2[TLS Layer] TLS2 --> KCP2[KCP Protocol] KCP2 --> D2[DERO Node 2] ``` | Layer | Technology | Purpose | |-------|-----------|---------| | **Transport** | UDP | Low latency, reduced kernel exposure | | **Reliability** | KCP | Reliable delivery over UDP | | **Encryption** | TLS | Confidentiality and integrity | | **Authentication** | Self-signed certs | No central authority | **Source:** `p2p/controller.go:34-35, 48, 609` --- ## TLS Implementation ### Self-Signed Certificates Simplified from source โ€” see `p2p/tlsconfig.go` for full implementation (`p2p/controller.go:717-776`): ```text // Simplified pseudocode โ€” actual source handles PEM encoding, error checks, etc. func generate_random_tls_cert() tls.Certificate { key = ecdsa.GenerateKey(elliptic.P256(), rand.Reader) tml = x509.Certificate{ SerialNumber: big.NewInt(randomSerial), } certDER = x509.CreateCertificate(rand.Reader, &tml, &tml, &key.PublicKey, key) // PEM-encode certDER and key, then: return tls.X509KeyPair(certPem, keyPem) } // Applied to connections tlsconfig = &tls.Config{ Certificates: []tls.Certificate{generate_random_tls_cert()} } tlsconn = tls.Server(conn, tlsconfig) ``` **Why self-signed?** - โœ… No certificate authorities (decentralized) - โœ… Each node generates own cert - โœ… No trusted third parties - โœ… Prevents network-level eavesdropping --- ## Why HTTPS is intentionally absent from RPC Every integrator who looks at the DERO daemon eventually asks: "why doesn't `derod` ship HTTPS on the RPC port?" The answer is two-part, and Captain has stated it directly: https is not supported intentionally. HTTPS gives false sense of security as certificate issuer has the private key to decrypt the traffic. And issuer can share the private-keys to others also when required. https can only help with local ISP/telecom sniffing, In that case use vpn etc.. **The two arguments unpacked:** 1. **HTTPS as a trust model is compromised by design.** A public CA can mint a valid certificate for any domain it wants (sometimes under legal compulsion, sometimes through compromise) and from that point, any "encrypted" HTTPS session can be silently intercepted. The padlock icon does not mean the traffic is private from the CA, only that it's private from passive sniffers on the wire. 2. **VPN is the right tool for the only legitimate HTTPS use case.** If your concern is local ISP / telecom / coffee-shop wifi sniffing, a VPN solves it at the transport layer โ€” without inheriting the CA-as-trusted-third-party problem. RPC traffic should already be on a trusted bus (`127.0.0.1`, a private VPN, an SSH tunnel, WireGuard). The architectural pattern that follows from this: | Port | Protocol | Encryption | Why | |---|---|---|---| | P2P (`10101`) | TLS over KCP/UDP | **Self-signed TLS** (per the section above) | Nodes talk across the public internet; encryption is required, but CAs are unwanted | | Daemon RPC (`10102`) | Plain HTTP | None (local trust) | Designed for `127.0.0.1` traffic; if you tunnel it, the tunnel provides encryption | | Wallet RPC (`10103`) | Plain HTTP | None (local trust) | Same model as daemon RPC | If you need to expose RPC over a network, **don't add HTTPS to `derod`** โ€” put it behind an authenticated TLS terminator you control (nginx, Caddy, an SSH tunnel, WireGuard). The threat model assumes the RPC port is on a trusted bus, and the encryption decision is delegated to whatever transport you choose to expose it over. --- ## ECDSA vs RSA Choice ### Performance Comparison **From source code comments** (`p2p/controller.go:721-734`): ```go /* RSA can do only 500 exchanges per second * EC256 does roughly 20000 exchanges per second */ // DERO chose ECDSA (P256) key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) ``` | Algorithm | Handshakes/Second | DERO's Choice | |-----------|------------------|---------------| | **RSA** | ~500 | โŒ Too slow | | **ECDSA P256** | ~20,000 | โœ… Used | **Why this matters:** - Enterprise services handle thousands of connections/second - Fast handshakes = better scalability - 40ร— performance improvement --- ## UDP vs TCP ### Why DERO Uses UDP | Aspect | TCP | UDP (with KCP) | |--------|-----|----------------| | **Network Overhead** | Higher | Lower | | **Kernel Exposure** | More syscalls | Fewer syscalls | | **Latency** | Higher | Lower | | **Reliability** | Built-in | KCP adds it | | **For Blockchain** | Slower propagation | Faster propagation | **KCP (UDP-based reliability):** - Provides TCP-like reliability over UDP - Lower latency than TCP - Configurable for blockchain needs - Used by many high-performance systems **Source:** `p2p/controller.go:48` - `github.com/xtaci/kcp-go/v5` --- ## Network Privacy Stack ``` Layer 1: UDP Transport โ†’ Low latency, reduced overhead Layer 2: KCP Protocol โ†’ Reliable delivery Layer 3: TLS Encryption โ† PRIVACY LAYER โ†’ Encrypted communication โ†’ Self-signed certificates โ†’ No eavesdropping possible Layer 4: DERO Protocol โ†’ Block/TX propagation โ†’ Encrypted by TLS ``` --- ## What TLS Protects **Network-Level Attacks Prevented:** | Attack | Without TLS | With TLS | |--------|-------------|----------| | **Eavesdropping** | ISP sees all data | โœ… Only sees encrypted packets | | **Tampering** | Can modify packets | โœ… Detected and rejected | | **Traffic Analysis** | Can identify TX types | โš ๏ธ Timing still visible | | **MITM** | Possible | โš ๏ธ Not prevented (no cert verification) | **What TLS does NOT hide (network layer metadata):** - โš ๏ธ Your IP address (visible at network layer) - โš ๏ธ Packet sizes (observable by network) - โš ๏ธ Connection timing (metadata analysis) - โš ๏ธ That you're using DERO (traffic patterns) *Note: These limitations apply to ALL TLS implementations (network layer metadata is below TLS's encryption layer)* **Additional privacy:** DERO supports SOCKS proxy (for Tor/other proxies): ```bash # Run daemon through Tor (Tor must be running on port 9050) ./derod --socks-proxy=127.0.0.1:9050 # Or through any SOCKS5 proxy ./derod --socks-proxy=proxy_ip:port # Source: cmd/derod/main.go:62, 75 # Flag: --socks-proxy= Use a proxy to connect to network. ``` **Note:** VPN would hide DERO usage from ISP, but is NOT configurable via daemon (system-level). --- ## Network Configuration **Default ports:** ```bash # Mainnet P2P: 10101 (encrypted UDP/KCP/TLS) RPC: 10102 (HTTP, local only) # Testnet P2P: 40401 (encrypted UDP/KCP/TLS) RPC: 40402 (HTTP, local only) ``` **Firewall rules:** ```bash # Allow P2P (required) sudo ufw allow 10101/udp # RPC should be local-only (security) # No firewall rule needed for RPC ``` **Source:** `config/config.go` - Network port constants --- ## Key Advantages **1. Privacy** - โœ… ISP cannot read network traffic - โœ… Government cannot inspect packets - โœ… No plaintext transaction broadcasts **2. Security** - โœ… Prevents packet tampering - โœ… Authenticates peers - โœ… Protects integrity **3. Performance** - โœ… Fast handshakes (20,000/sec with ECDSA) - โœ… Low latency (UDP-based) - โœ… Efficient propagation **4. Decentralization** - โœ… No certificate authorities - โœ… Self-signed certs - โœ… No central trust point --- ## Comparison with Other Blockchains | Blockchain | Network Encryption | Protocol | Performance | |------------|-------------------|----------|-------------| | **Bitcoin** | โœ… BIP 324 (v2 transport, since Core 26.0) | TCP | Slower, public | | **Ethereum** | โœ… RLPx (ECIES encrypted transport) | TCP | Slower, public | | **Other Privacy Coins** | โš ๏ธ Varies by implementation | TCP | Slower, public | | **DERO** | โœ… TLS | UDP/KCP | Faster, private | **DERO = Only blockchain with encrypted P2P layer** --- ## Technical Implementation ### Connection Flow ``` Outgoing connection: 1. Create KCP/UDP connection 2. Wrap with TLS (self-signed cert) 3. Perform handshake 4. Exchange blockchain data (encrypted) Incoming connection: 1. Accept KCP/UDP connection 2. Wrap with TLS (self-signed cert) 3. Verify handshake 4. Serve blockchain data (encrypted) ``` **Source code:** - TLS setup: `p2p/controller.go:551, 609` - Outgoing: `p2p/controller.go:398` - `tls.Client(conn, &tls.Config{InsecureSkipVerify: true})` - Incoming: `p2p/controller.go:609` - `tls.Server(conn, tlsconfig)` --- ## Limitations & Mitigations **What TLS Encrypts:** - โœ… All packet contents - โœ… Transaction data - โœ… Block data - โœ… Peer communications **What TLS Does NOT Hide:** - โš ๏ธ That you're using DERO - โš ๏ธ Connection timing - โš ๏ธ Packet sizes - โš ๏ธ Your IP address **Additional Privacy Layers:** ```bash # Use Tor for IP privacy torify ./derod # Or use VPN # Hides that you're using DERO from ISP ``` --- ## Key Takeaways **DERO's encrypted network provides:** - โœ… **TLS encryption** - All P2P traffic encrypted - โœ… **UDP/KCP protocol** - Fast, low latency - โœ… **ECDSA certificates** - 20,000 handshakes/sec (40ร— faster than RSA) - โœ… **Self-signed** - No certificate authorities - โœ… **Privacy** - ISP cannot read network data - โœ… **Security** - Tampering detected and prevented > [!WARNING] > **Note:** TLS protects network layer. For complete privacy, DERO also uses ring signatures (sender), homomorphic encryption (amounts), and bulletproofs (validation). --- ## Further Reading - [Transaction Privacy](/privacy/transaction-privacy.md) - How all privacy layers work together - [Running a Node](/basics/running-a-node.md) - Setup your own node - [DERO Daemon](/basics/daemon.md) - Understanding daemon operations **Source Code:** - Network implementation: `p2p/controller.go` - TLS cert generation: `p2p/controller.go:717-776` - KCP/UDP: `github.com/xtaci/kcp-go/v5` --- --- title: "Erasure Coded Blocks: Resilient Block Propagation | DERO Blockchain" description: "DERO uses Reed-Solomon erasure coding to split blocks into 48 chunks and disperse them across the P2P network, enabling reconstruction from any 16 pieces for fast, resilient propagation." keywords: ["erasure coding", "Reed-Solomon", "block propagation", "DERO network", "data shards", "parity shards", "P2P resilience", "chunk dispersal", "network redundancy"] date: "2024-08-26" lastUpdated: "2026-02-16" authors: ["DHEBP"] slug: "erasure-coding" canonicalUrl: "https://derod.org/features/erasure-coding" tags: ["features", "erasure-coding", "network", "P2P", "Reed-Solomon"] --- # Erasure Coded Blocks DERO uses **erasure coding** to improve block propagation across its peer-to-peer network. Rather than transmitting entire blocks as a monolithic unit, DERO splits block data into multiple chunks, generates redundant parity chunks, and disperses them across peers. Any peer receiving a sufficient subset of chunks can reconstruct the full block โ€” even if the majority of chunks are lost or delayed. > [!NOTE] > **Innovation:** DERO erasure codes each block into 48 chunks and disperses them across the network. Any peer receiving just 16 of the 48 chunks can fully reconstruct the original block. --- ## What Is Erasure Coding? Erasure coding is a forward error correction technique that adds mathematical redundancy to data. Unlike simple duplication, it uses algorithms to generate parity shards that allow full reconstruction from any sufficient subset of pieces. In DERO: - A block is serialized and split into **data shards** - Additional **parity shards** are generated using [Reed-Solomon coding](https://en.wikipedia.org/wiki/Reed%E2%80%93Solomon_error_correction) - Shards are dispersed across peers in the network - Any peer receiving enough shards (data or parity) can reconstruct the entire block This improves network resilience against packet loss, latency spikes, and partial connectivity โ€” without requiring full block retransmission. --- ## The 48-Chunk Layout DERO's erasure coding configuration uses a **16/32 Reed-Solomon scheme**: | Parameter | Value | Description | |-----------|-------|-------------| | Data shards | 16 | Original block data split into 16 pieces | | Parity shards | 32 | Redundant parity pieces generated | | **Total chunks** | **48** | All pieces dispersed across the network | | **Reconstruction threshold** | **16** | Minimum chunks needed to rebuild the block | **Source:** `p2p/chunk_server.go:335-347` ```go // 16 data blocks, 32 parity blocks RS code // if the peer receives any 16 blocks in any order, they can reconstruct entire block enc, _ := reedsolomon.New(16, 32) ``` --- ## How It Works ```mermaid graph LR BLK[Block
1.6 MB] --> SER[CBOR
Serialization] SER --> SPL[Split into
16 Data Shards] SPL --> RS[Reed-Solomon
Encoding] RS --> CHK[48 Total Chunks
~100 KB each] CHK --> P1[Peer A] CHK --> P2[Peer B] CHK --> P3[Peer C] CHK --> PN[Peer N...] ``` Consider a **1.6 MB block** being propagated: 1. **Serialization** โ€” The complete block is serialized using CBOR encoding 2. **Splitting** โ€” The 1.6 MB payload is divided into 16 data shards (~100 KB each) 3. **Parity generation** โ€” Reed-Solomon generates 32 parity shards (~100 KB each) 4. **Dispersal** โ€” 48 chunks total (~4.8 MB of data) are distributed across peers 5. **Reconstruction** โ€” Any peer receiving any 16 of the 48 chunks reconstructs the original 1.6 MB block > [!NOTE] > **Resilience:** A peer can lose up to **32 of 48 chunks** (66% packet loss) and still fully reconstruct the block. --- ## Data Expansion Erasure coding trades **bandwidth for reliability**. This tradeoff results in data expansion: ``` Expansion Factor = Total Chunks / Data Chunks = 48 / 16 = 3ร— ``` A 1 MB block becomes ~3 MB of dispersed chunks. This is intentional redundancy โ€” not accidental bloat. The tradeoff is worthwhile: fast, resilient propagation across an adversarial network. ### Hard Limits The implementation enforces practical bounds on expansion: **Source:** `p2p/chunk_server.go:12-16`, `p2p/chunk_server.go:341-345` ```go const MAX_CHUNKS uint8 = 255 // Maximum 255 chunks total // Minimum requirements: if data_shard_count < 10 { panic(fmt.Errorf("data shard must be >= 10, actual %d", data_shard_count)) } if parity_shard_count < data_shard_count { panic(fmt.Errorf("parity shard must be equal or more than data shards")) } ``` | Constraint | Value | Effect | |------------|-------|--------| | Max total chunks | 255 | Upper bound on shard count | | Min data shards | 10 | Prevents excessive expansion | | Parity โ‰ฅ Data | Enforced | Guarantees meaningful redundancy | | **Max expansion** | **~25.5ร—** | `255 / 10` theoretical limit | These limits balance network efficiency, memory constraints, and latency. ### 100ร— Block Size Scalability DERO's official documentation states that erasure coding *"allows 100x block size without increasing propagation delays."* This is a separate claim from the 3ร— data expansion โ€” and both are correct. They measure different things: | Metric | Value | What it measures | |--------|-------|-----------------| | **Data expansion** | 3ร— | Bandwidth cost per block (48 chunks / 16 data shards) | | **Block size scalability** | up to 100ร— | How much larger blocks can be while maintaining fast propagation | **Why erasure coding enables larger blocks:** In traditional blockchains, a block must be transmitted in full to every peer before it can propagate further. If you double the block size, you roughly double the propagation time across the network. This creates a practical ceiling on block size โ€” larger blocks mean slower propagation, more orphans, and reduced security. Erasure coding breaks this bottleneck: 1. **Parallel dispersal** โ€” 48 small chunks propagate simultaneously across different peers, rather than one large block moving sequentially 2. **Partial reconstruction** โ€” Peers don't need the full 48 chunks; any 16 suffice, so propagation completes as soon as the fastest 16 paths deliver 3. **Reduced per-peer load** โ€” Each peer only transmits a small chunk (~1/48th of the expanded data), not the entire block 4. **Network-wide parallelism** โ€” While peer A sends chunk 1 to peer B, peer C is already forwarding chunk 7 to peer D The net effect: a 100 MB block broken into 48 chunks of ~6.25 MB each propagates far faster than sending 100 MB sequentially to each peer โ€” even though the total data in the network is 3ร— larger. The parallelism more than compensates for the redundancy overhead. > [!NOTE] > **The tradeoff:** Pay 3ร— in total bandwidth to unlock dramatically larger block sizes without sacrificing propagation speed. This is a key enabler of DERO's scalability. --- ## Chunk Dispersal Chunks are distributed using a **round-robin strategy** across peers, prioritized by latency: **Source:** `p2p/connection_pool.go:394-467` ```go // Each peer gets a specific chunk based on count modulo total chunks cid := count % chunk_count // Rotates through chunks 0-47 // Build chunk identifier: [32-byte block ID][1-byte chunk ID][32-byte header hash] var chunkid [32 + 1 + 32]byte copy(chunkid[:], blid[:]) chunkid[32] = byte(cid) copy(chunkid[33:], hhash[:]) ``` ### Dispersal Process ```mermaid graph TD SORT[Sort peers by latency
fastest first] --> ASSIGN[Assign chunk IDs
round-robin] ASSIGN --> SEND[Send chunks
one per peer] SEND --> INV[Peers broadcast INV
inventory messages] INV --> SPREAD[Chunks spread
across network] ``` 1. **Latency-based peer sorting** โ€” Peers are sorted by connection latency (fastest first) 2. **Bandwidth factor** โ€” Environment variable `BW_FACTOR` controls redundancy (default 1) 3. **Chunk rotation** โ€” Each peer receives chunk `count % 48`, cycling through all 48 chunks 4. **Minimum distribution** โ€” Every connected peer gets at least one chunk 5. **Rebroadcast** โ€” When a peer receives a chunk, it broadcasts an INV (inventory) message to its peers **Source:** `p2p/rpc_notifications.go:32-94`, `p2p/connection_pool.go:483-534` --- ## Reconstruction When a peer collects enough chunks, reconstruction begins automatically: **Source:** `p2p/chunk_server.go:176-232` ```go // 1. Collect available chunks if uint(chunk_count) < chunk.CHUNK_NEED { // Need at least 16 return nil // Wait for more chunks } // 2. Build shard array (nil for missing chunks) var shards [][]byte for i := 0; i < int(chunk.CHUNK_COUNT); i++ { if chunks_per_block.ChunkCollection[i] == nil { shards = append(shards, nil) } else { shards = append(shards, chunks_per_block.ChunkCollection[i].CHUNK_DATA) } } // 3. Reconstruct missing shards enc, _ := reedsolomon.New(int(chunk.CHUNK_NEED), int(chunk.CHUNK_COUNT-chunk.CHUNK_NEED)) if err := enc.Reconstruct(shards); err != nil { return nil } // 4. Join shards back into original payload var writer bytes.Buffer if err := enc.Join(&writer, shards, int(chunk.DSIZE)); err != nil { return nil } // 5. Deserialize and process block if err := cbor.Unmarshal(writer.Bytes(), &cbl); err != nil { return nil } ``` --- ## Failure Scenarios ### Normal Operation - Peer receives 16+ chunks from different sources - Reconstruction succeeds, block is validated and added to the chain - Remaining arriving chunks are ignored (block already reconstructed) ### High Packet Loss - Fewer than 16 chunks arrive within the timeout window - Peer waits for additional chunks or requests missing ones via `GetObject` - If insufficient chunks arrive within 3 minutes, the chunk set expires and is cleaned up **Source:** `p2p/chunk_server.go:35-47` ```go func chunks_clean_up() { chunk_map.Range(func(key, value interface{}) bool { chunks_per_block := value.(*Chunks_Per_Block_Data) if time.Now().Sub(chunks_per_block.Created) > time.Second*180 { chunk_map.Delete(key) // Expire after 3 minutes } return true }) } ``` ### Malicious Chunks - Each chunk includes a hash of its data (`CHUNK_HASH`) - Corrupted chunks fail hash verification and are rejected - Peers sending bad chunks can be banned **Source:** `p2p/chunk_server.go:72-87` ```go if chunk.CHUNK_HASH[chunk.CHUNK_ID] != crypto.Keccak256_64(chunk.CHUNK_DATA) { return fmt.Errorf("Corrupted Chunk") // Hash mismatch } ``` --- ## RAID Analogy Erasure coding in DERO is conceptually similar to **RAID** in storage systems โ€” but applied to the network layer: | RAID Level | Description | DERO Equivalent | |------------|-------------|-----------------| | **RAID 0** | Striping, no redundancy | No erasure coding (just split blocks) | | **RAID 1** | Mirroring (full duplication) | Sending full block to all peers (inefficient) | | **RAID 5** | Striping + distributed parity | Similar concept but fixed parity disks | | **RAID 6** | Striping + dual parity | More parity, can lose 2 disks | | **DERO EC** | 16 data + 32 parity shards | Can lose up to 32 of 48 chunks | **Key differences from RAID:** - โœ… **Network vs. Storage** โ€” RAID protects against disk failures; DERO protects against network propagation failures - โœ… **Dynamic dispersal** โ€” RAID uses fixed disks; DERO disperses across dynamic peer connections - โœ… **Any subset works** โ€” Unlike RAID with fixed parity locations, any 16 of 48 chunks suffice - โœ… **No hot spares** โ€” Redundancy comes from oversharing, not standby peers Think of it as **"RAID for the network"** โ€” instead of protecting against disk failures, it protects against packet loss, peers going offline mid-propagation, network congestion, and asymmetric connectivity. --- ## What Erasure Coding Is NOT > [!WARNING] > Erasure coding is a **propagation optimization**, not a privacy or consensus mechanism. | Misconception | Reality | |---------------|---------| | Encryption | Chunks are not encrypted โ€” they are split and redundant | | Privacy feature | Anyone with 16 chunks can reconstruct the block | | Compression | It **expands** data (3ร—), not compresses it | | Consensus mechanism | It propagates blocks but doesn't validate them | For privacy features, see [Ring Signatures](/privacy/ring-signatures.md), [Homomorphic Encryption](/privacy/homomorphic-encryption.md), and [Bulletproofs](/privacy/bulletproofs.md). --- ## Compression The erasure coding path does **not** apply additional compression (zstd, gzip, snappy, etc.). The flow is strictly: ``` Block โ†’ CBOR Serialization โ†’ Reed-Solomon Encoding โ†’ Chunk Transmission ``` The Reed-Solomon library adds redundancy only โ€” it does not compress. CBOR provides compact binary encoding, but no explicit compression step occurs before chunking. --- ## Implementation Details ### Block Chunk Structure **Source:** `p2p/wire_structs.go:148-158` ```go type Block_Chunk struct { Type uint16 `cbor:"T"` // Object type HHash [32]byte `cbor:"BLH"` // Header hash for verification BLID [32]byte `cbor:"BLID"` // Block ID this chunk belongs to DSIZE uint `cbor:"DSIZE"` // Original data size in bytes BLOCK []byte `cbor:"BL"` // Block header and miniblock data CHUNK_COUNT uint `cbor:"CC"` // Total chunks (48) CHUNK_NEED uint `cbor:"CN"` // Chunks needed for reconstruction (16) CHUNK_HASH []uint64 `cbor:"CH"` // All chunk hashes (48 hashes) CHUNK_ID uint `cbor:"CID"` // This chunk's ID (0-47) CHUNK_DATA []byte `cbor:"CD"` // This chunk's payload data } ``` ### Libraries Used | Library | Purpose | |---------|---------| | `github.com/klauspost/reedsolomon` | Efficient Go Reed-Solomon implementation | | `github.com/fxamacker/cbor/v2` | Binary serialization for wire format | | `crypto.Keccak256_64` | Fast 64-bit truncated hashes for chunk verification | ### Source Files | File | Purpose | |------|---------| | `p2p/chunk_server.go` | Core chunk creation, validation, and reconstruction | | `p2p/connection_pool.go` | Chunk dispersal and broadcast logic | | `p2p/rpc_notifications.go` | Chunk INV handling and rebroadcast | | `p2p/rpc_object_request.go` | Chunk request/response protocol | | `p2p/wire_structs.go` | Chunk data structure definitions | --- ## Key Takeaways **DERO's erasure coding system:** - โœ… **Splits** blocks into 16 data shards using Reed-Solomon coding - โœ… **Generates** 32 parity shards for redundancy - โœ… **Disperses** 48 total chunks across the peer network - โœ… **Reconstructs** full blocks from any 16 received chunks - โœ… **Tolerates** up to 66% chunk loss during propagation - โœ… **Protects** against packet loss, peer dropout, and network congestion > [!NOTE] > **Design philosophy:** Trade a 3ร— bandwidth expansion for robust block propagation even in adversarial or congested network conditions. --- ## Further Reading - [Encrypted Network](/features/encrypted-network.md) โ€” TLS encryption for peer connections - [Graviton](/features/graviton.md) โ€” DERO's storage engine - [Transaction Privacy](/privacy/transaction-privacy.md) โ€” How all privacy layers work together **Source Code:** - Chunk server: `p2p/chunk_server.go` - Dispersal logic: `p2p/connection_pool.go` - Reed-Solomon: `github.com/klauspost/reedsolomon` --- --- title: "Why DERO is Built in Go | DERO Blockchain" description: "How Go's concurrency, performance, and security features enable DERO's unique blockchain capabilities - from encrypted balances to high-throughput P2P networking." keywords: ["Golang", "DERO development", "blockchain programming", "Go concurrency", "blockchain performance", "software architecture", "DERO codebase"] date: "2024-08-26" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/golang.jpeg" slug: "golang" canonicalUrl: "https://derod.org/features/golang" tags: ["features", "golang", "development", "performance", "architecture"] --- # Why Go for DERO? ![Golang](/assets/golang.jpeg) DERO was built from scratch in Go (Golang) - a deliberate choice that enables the unique features other blockchains can't achieve. Not a fork, not a copy - original code leveraging Go's strengths. > [!NOTE] > **Written from scratch:** DERO is NOT a fork. Every line of code designed specifically for homomorphic encryption, ring signatures, and private smart contracts. --- ## Why Go Was Chosen | Reason | How DERO Uses It | |--------|------------------| | **Concurrency** | Thousands of P2P connections simultaneously | | **Performance** | Fast cryptographic operations (bulletproofs, ElGamal) | | **Memory Safety** | Prevents exploits in consensus code | | **Cross-Platform** | Runs on Linux/Windows/Mac from same codebase | | **Fast Compilation** | Quick development iterations | --- ## Real DERO Examples ### 1. Concurrent P2P Connections **From source** (`p2p/controller.go:542-545`): ```go // Handle thousands of connections concurrently go func() { time.Sleep(2 * time.Second) connection.dispatch_test_handshake() }() ``` **Each connection runs in its own goroutine - DERO can handle 10,000+ concurrent peers effortlessly** ### 2. Parallel Transaction Validation **From source** (`blockchain/transaction_verify.go`): ```go // Validate multiple transactions in parallel for t := range tx.Payloads { go func(payload_index int) { // Verify bulletproofs // Check ring signatures // Validate homomorphic operations }(t) } ``` **Go's goroutines make parallel validation fast** ### 3. Cryptographic Performance **ElGamal operations** (`cryptography/crypto/algebra_elgamal.go:69-74`): ```go func (e *ElGamal) Add(addendum *ElGamal) *ElGamal { return ConstructElGamal( new(bn256.G1).Add(e.Left, addendum.Left), new(bn256.G1).Add(e.Right, addendum.Right)) } ``` **Go's performance enables fast homomorphic balance updates (under 25ms)** --- ## Go vs Other Blockchain Languages | Language | Used By | DERO Couldn't Use Because | |----------|---------|--------------------------| | **C++** | Bitcoin | Memory unsafe, harder to maintain | | **Rust** | Polkadot | Slower development, steep learning curve | | **Solidity** | Ethereum | Smart contract language only, not for core | | **Python** | (tools only) | Too slow for blockchain consensus | | **Go** | **DERO** | โœ… Perfect fit | --- ## Key Go Features DERO Leverages ### Goroutines (Lightweight Threads) ```go // Launch 10,000 goroutines - no problem for i := 0; i < 10000; i++ { go handleConnection(conn) } // Each uses only ~2KB memory // Total: ~20MB for 10,000 connections ``` **Enables:** Massive P2P scalability ### Channels (Safe Communication) ```go // Thread-safe message passing Exit_Event := make(chan bool) // Signal all goroutines to stop close(Exit_Event) ``` **Enables:** Clean shutdown, no race conditions ### Built-in Crypto Libraries ```go import "crypto/sha256" import "crypto/ecdsa" import "crypto/tls" // Fast, battle-tested implementations ``` **Enables:** Secure P2P, fast hashing ### Memory Safety ```go // Go prevents: // - Buffer overflows // - Use-after-free // - Null pointer dereferences (with panic recovery) // Critical for consensus code ``` **Enables:** Secure blockchain operations --- ## DERO's Go Stack **Go version:** 1.17+ (check `go.mod`) **Key packages used:** ```go import "crypto/tls" // P2P encryption import "crypto/ecdsa" // Certificates import "github.com/xtaci/kcp-go/v5" // UDP reliability import "github.com/deroproject/derohe/cryptography/bn256" // ElGamal ``` --- ## Performance Benefits ### Real Measurements | Operation | Time | Enabled By | |-----------|------|------------| | **Transaction validation** | under 25ms | Go's speed + goroutines | | **TLS handshakes** | 20,000/sec | ECDSA in Go | | **ElGamal operations** | ~10ms | Optimized Go math | | **P2P connections** | 10,000+ simultaneous | Goroutines | **Source:** `README.md` - Performance claims, verified in codebase --- ## Development Advantages ### Cross-Platform Compilation ```bash # Build for all platforms from one codebase GOOS=linux GOARCH=amd64 go build # Linux GOOS=windows GOARCH=amd64 go build # Windows GOOS=darwin GOARCH=amd64 go build # Mac Intel GOOS=darwin GOARCH=arm64 go build # Mac M1/M2 ``` **Result:** Single codebase, multiple platforms ### Fast Iteration ```bash # Compile entire DERO daemon go build ./cmd/derod/ # Takes seconds, not minutes ``` **Enables:** Quick bug fixes and feature additions --- ## DERO-Specific Examples ### Homomorphic Encryption in Go ```go // From cryptography/crypto/algebra_elgamal.go type ElGamal struct { Left *bn256.G1 // Elliptic curve point Right *bn256.G1 // Elliptic curve point } // Add encrypted values (homomorphic!) func (e *ElGamal) Add(other *ElGamal) *ElGamal { return ConstructElGamal( new(bn256.G1).Add(e.Left, other.Left), new(bn256.G1).Add(e.Right, other.Right)) } ``` **Go makes complex crypto operations readable and maintainable** ### Concurrent Mining ```go // Multiple miners can connect simultaneously for { conn, _ := listener.Accept() go handleMiner(conn) // Each in own goroutine } ``` **Go's goroutines enable 10,000+ miner connections per daemon** --- ## Key Takeaways **Go enables DERO's unique features:** - โœ… **Fast cryptography** - Homomorphic encryption, bulletproofs - โœ… **Massive P2P** - 10,000+ concurrent connections - โœ… **Safe consensus** - Memory safety prevents exploits - โœ… **Quick development** - Fast compilation, easy maintenance - โœ… **Cross-platform** - One codebase, all platforms **DERO wouldn't be possible in most other languages** > [!NOTE] > **Want to contribute?** DERO's Go codebase is open source and readable. No complex macros, no manual memory management - just clean, concurrent code. --- ## Further Reading - [DERO GitHub](https://github.com/deroproject/derohe) - Full source code - [Encrypted Network](/features/encrypted-network.md) - TLS implementation in Go - [DVM](/features/dvm.md) - Smart contract VM in Go --- --- title: "Graviton: DERO's Immutable Key-Value Database | DERO Blockchain" description: "Explore Graviton, DERO's specialized key-value store database that securely manages encrypted account balances with cryptographic proofs and censorship-resistant design." keywords: ["Graviton database", "key-value store", "blockchain database", "encrypted storage", "append-only database", "tamper-proof database", "DERO infrastructure", "cryptographic proofs", "database snapshots", "decentralized storage"] date: "2024-08-26" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/graviton.png" slug: "graviton" canonicalUrl: "https://derod.org/features/graviton" tags: ["features", "graviton", "database", "storage", "infrastructure"] --- # Graviton ![Graviton](/assets/graviton.png) At the core of Dero's infrastructure resides Graviton, a purpose-built key-value store database meticulously crafted to meet the intricate demands of DeroHE. Serving as the primary database for Dero, Graviton performs a crucial role in securely managing and storing all account balances in an encrypted state. It exhibits a remarkable similarity to ZFS, a renowned file system celebrated for its integrity and data protection attributes. Graviton is more than a database; it stands as a robust, feature-rich, and corruption-resistant key-value store database, well-suited for diverse applications and environments. Its innovative design ensures data integrity, facilitating convenient snapshots for backups while enabling live updates without compromising the database's stability. This unique approach ensures Graviton's adaptability and reliability within the ever-evolving ecosystem of DeroHE. Similar to a bank, Graviton updates balances in an encrypted manner, relying solely on cryptographic proofs to maintain accuracy, ensuring unparalleled privacy and security for account holders. However, what truly sets Graviton apart is its ability to store uncompiled code within its database structure, eliminating the reliance on a centralized code source. This pioneering feature empowers the entire Dero network by providing resilience against censorship attempts, even in scenarios where entities attempt to shut down the entire internet. Graviton's decentralized nature enables the restoration of the entire Dero network from a single node copy, making it resistant to disruptions or censorship attempts. Graviton represents an authenticated and append-only key-value store that supports version tracking, snapshots, cryptographic proofs, and efficient diffing mechanisms, addressing significant limitations observed in traditional databases. Its open-source nature, seamless integration into Golang applications, and unwavering commitment to quality code further establish its significance in the database landscape. ### Append-only data storage system An append-only data storage system, often employed in blockchain technology, establishes a framework that guarantees data immutability, security, and transparency. This system operates by enforcing a strict rule where any new data can only be added without modifying or deleting the existing information. This characteristic ensures that once data is recorded, it remains unaltered and becomes effectively immutable. The architecture prevents retroactive changes or deletions to previously stored information, fostering an environment of data integrity and trustworthiness. The append-only nature of this system plays a pivotal role in maintaining a transparent and tamper-proof record of all transactions or records. By restricting modifications to appending new data, each addition becomes a permanent and verifiable entry in the system's log, contributing to the overall security and auditability of the stored information. This approach offers robust protection against unauthorized alterations or manipulations while upholding a transparent history of events or data changes, bolstering trust and reliability within the system. ### Graviton API Graviton's minimalistic API, scalability for exabyte-sized data stores, decoupled storage layer, cryptographic proof generation, versatile storage options, and complete code coverage make it a reliable and adaptable database solution suitable for various applications. Graviton's codebase is available on GitHub (https://github.com/deroproject/graviton) Learn more: [Privacy Suite - How Graviton stores encrypted balances](/privacy/homomorphic-encryption.md) --- --- title: "Private Smart Contracts: DERO's Confidential Execution | DERO Blockchain" description: "Discover DERO's groundbreaking private smart contracts that enable secure, confidential transactions with encrypted computation and enhanced privacy protection." keywords: ["private smart contracts", "DERO contracts", "encrypted smart contracts", "confidential transactions", "blockchain privacy", "secure smart contracts", "privacy-preserving computation", "data confidentiality", "trustless transactions", "regulated compliance"] date: "2024-08-26" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/smart_contracts.jpeg" slug: "smart-contracts" canonicalUrl: "https://derod.org/features/smart-contracts" tags: ["features", "smart-contracts", "privacy", "DVM", "encryption"] --- # Private Smart Contracts ![Private Smart Contracts](/assets/smart_contracts.jpeg) Private smart contracts offer strong security, confidentiality, and privacy, safeguarding sensitive data throughout contract execution. This method aligns with compliance standards and holds diverse applications across multiple industries. | Advantages | Description | |--------------------------------|------------------------------------------------------------------------------------------------------| | Enhanced Privacy | Private token balances via homomorphic encryption โ€” contract state is public, but token balances become encrypted in user wallets after issuance. | | Confidential Data | Safeguarding contract terms and data confidentiality by limiting access to authorized parties. | | Secure Computation | Conducting secure computations without revealing sensitive data, ensuring confidentiality. | | Data Integrity | Protecting encrypted data against unauthorized modifications, maintaining contract integrity. | | Compliance | Aligning with data privacy regulations by ensuring data encryption throughout contract execution. | | Trustless | Enabling secure transactions without complete reliance on trust in involved parties. | | Cross-Industry Applications | Extending applications to various sectors that demand secure data processing within contracts. | --- --- title: "DERO Usernames: Simplified Blockchain Transactions | DERO Blockchain" description: "Experience DERO's built-in username feature that replaces complex wallet addresses with personalized names, making cryptocurrency transfers simpler, safer, and more user-friendly." keywords: ["DERO usernames", "wallet addresses", "simplified transactions", "blockchain identifiers", "cryptocurrency transfers", "personalized wallets", "secure transactions", "DERO wallet", "user-friendly crypto", "blockchain identity"] date: "2024-08-26" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/JaneDoe.png" slug: "usernames" canonicalUrl: "https://derod.org/features/usernames" tags: ["features", "usernames", "name-service", "UX", "usability"] --- # Usernames ![Usernames](/assets/JaneDoe.png) ## User-friendly Wallet Addresses Sending and receiving funds in the world of cryptocurrency often involves sharing lengthy wallet addresses. However, with DERO's built-in username feature, you can register a personalized name and associate it with your wallet address on the network. Once registered, your username can be used by others to send funds, Non-fungible Assets (NFAs) and private messages to your wallet. #### Benefits of Usernames By registering a name, you not only simplify the process of sending and receiving assets but also enhance security and reduce the risk of errors in transactions. Additionally, a username allows for easier identification and communication within the DERO ecosystem. #### Registering Your Name The process is simple. Just choose a name you'd like to associate with your wallet and register it using either the official [Dero CLI Wallet](https://github.com/deroproject/derohe/releases) or the official [Dero GUI Wallet](https://github.com/DEROFDN/Engram/releases). Names can have 6 or more characters in length. They are case sensitive so sending funds to `JaneDoe` is different than sending funds to `janedoe`. --- --- title: "DERO Protocol Integrity: Complete Technical Guide | DERO Blockchain" description: "Deep dive into DERO's mathematical integrity guarantees including transaction proofs, range proofs, negative transfer protection, and network consensus validation." keywords: ["DERO integrity", "protocol integrity", "transaction proofs", "range proofs", "bulletproofs", "negative transfer protection", "blockchain integrity", "cryptographic proofs"] date: "2025-01-20" lastUpdated: "2026-02-06" authors: ["DHEBP"] slug: "integrity" canonicalUrl: "https://derod.org/integrity" tags: ["integrity", "cryptography", "protocol", "technical", "proofs"] --- # DERO Protocol Integrity **Integrity is a mathematical guarantee, not a policy.** DERO's protocol integrity isn't achieved through secrecy or trust โ€” it's achieved through cryptographic proofs that are independently verifiable by anyone. **The Foundation:** Every DERO transaction requires six interlocking cryptographic proofs that must all pass. Fake one, and the cryptographic binding invalidates all six. These proofs are open source and independently verifiable by anyone. --- ## The Six Sigma Proof System Every DERO transaction requires **six sigma proof components** bound together through a cryptographic challenge hash. Faking one proof changes the hash, which invalidates all other proofs โ€” an all-or-nothing security model. ```mermaid flowchart LR TX["Transaction"] --> PROOFS["6 Sigma Proofs"] PROOFS --> HASH["Challenge Hash"] HASH --> VALID{"Valid?"} VALID -->|Yes| ACC["Accepted"] VALID -->|No| REJ["Rejected"] ``` **Source:** `cryptography/crypto/proof_verify.go` โ€” [Full technical breakdown โ†’](/integrity/transaction-proofs.md) --- ## Anatomy of a Transaction Follow a DERO transaction from creation to finality โ€” each row links to the full technical deep-dive. ### Phase 1: Building the Transaction Before a transaction leaves the wallet, the proof system is already at work. | What Happens | Learn More | |-------------|------------| | Wallet reads the sender's encrypted balance: 66 bytes, two curve points, zero plaintext | [Balance Mechanics](/integrity/balance-mechanics.md) | | Wallet generates six sigma proofs, all bound through a single challenge hash | [Transaction Proofs](/integrity/transaction-proofs.md) | | A_t encodes a combined 128-bit value: 64 bits transfer + 64 bits remaining. Bulletproof construction starts here | [Range Proofs](/integrity/range-proof-integrity.md) | ### Phase 2: Network Verification Every node that receives this transaction runs the same verification independently. | What Happens | Learn More | |-------------|------------| | First checkpoint: `uint64` overflow checks on fees and values. Fails fast before expensive crypto | [Overflow Protection](/integrity/overflow-protection.md) | | Five checkpoints in sequence: overflow, parity, polynomial recovery, challenge hash, inner product | [Verification Flow](/integrity/proof-verification-flow.md) | | Bulletproof soundness rejects any committed value outside the proven range โ€” including negative/wraparound amounts | [Negative Transfers](/integrity/negative-transfer-protection.md) | ### Phase 3: Acceptance and State Once verified, the transaction enters the mempool, gets mined into a block, and the chain state updates. | What Happens | Learn More | |-------------|------------| | Every node verifies independently and reaches the same conclusion. 18-second blocks, probabilistic finality | [Network Consensus](/integrity/network-consensus-validation.md) | | All ring members' encrypted balances change โ€” including decoys. Only the owner knows who sent | [Ring Members](/integrity/ring-member-behavior.md) | | Transaction proofs (consensus, secure) vs. payload proofs (display, fakeable by design) | [Proof Types](/integrity/payload-vs-transaction-proofs.md) | | October 2022 inflation claim: claims vs. evidence | [Inflation Claim](/integrity/inflation-claim.md) | --- ## Security Guarantees All cryptographic protections below rely on the hardness of ECDLP on the bn256 curve (see [Mathematical Foundation](#mathematical-foundation) below), except where noted. | Threat | Protection | |--------|------------| | **Negative transfers** | Bulletproof soundness (verifier-enforced range) | | **Transaction replay** | A_u key image + nonce/height + consensus rules | | **Invalid amounts** | 128-bit combined range proof | | **Forged transactions** | A_y proof (private key ownership) | | **Balance manipulation** | Homomorphic commitments | | **Arithmetic overflow** | Explicit `uint64` overflow checks *(deterministic integer arithmetic, not cryptographic)* | ### Honest Limitations | Limitation | What's Exposed | |------------|---------------| | **Timing analysis** | Transaction submission times are visible to connected peers | | **Network observation** | IP addresses are visible to peers (TLS encrypts content, not identity) | | **Metadata correlation** | Transaction frequency and patterns are observable on-chain | --- ## Verify It Yourself **Don't Trust, Verify:** All claims in this documentation can be independently verified against the DERO source code. | Protection | File | Lines | |------------|------|-------| | `Verify()` entry point | `cryptography/crypto/proof_verify.go` | 98 | | Overflow check | `cryptography/crypto/proof_verify.go` | 108-111 | | Parity check | `cryptography/crypto/proof_verify.go` | 136-141 | | Challenge hash | `cryptography/crypto/proof_verify.go` | 410-425 | | Inner product | `cryptography/crypto/proof_verify.go` | 457-460 | | Block time | `config/config.go` | 34 | | Balance init | `blockchain/transaction_execute.go` | 189-194 | ```bash git clone https://github.com/deroproject/derohe.git cd derohe # Verify any of the above: sed -n '108,110p' cryptography/crypto/proof_verify.go # Overflow check sed -n '410,425p' cryptography/crypto/proof_verify.go # Challenge hash sed -n '457,459p' cryptography/crypto/proof_verify.go # Inner product grep "BLOCK_TIME" config/config.go # Block time ``` --- ## Mathematical Foundation DERO's cryptographic proofs rely on the hardness of the elliptic curve discrete logarithm problem (ECDLP) on a bn256 (Barreto-Naehrig) curve -- the same curve family behind Ethereum's bn256 precompiles (EIP-196/197). No efficient algorithm is known for solving ECDLP on these parameters. Source: `cryptography/bn256/` --- --- title: "Balance Mechanics: Encrypted State Management | DERO Blockchain" description: "Technical deep dive into how DERO manages encrypted balances - the 66-byte structure, homomorphic operations, zero initialization, and what balance changes mean." keywords: ["encrypted balance", "DERO balance", "homomorphic encryption", "ElGamal", "balance mechanics", "encrypted state", "blockchain state"] date: "2025-01-20" lastUpdated: "2026-02-06" authors: ["DHEBP"] slug: "balance-mechanics" canonicalUrl: "https://derod.org/integrity/balance-mechanics" tags: ["security", "balances", "encryption", "state", "technical"] --- # Balance Mechanics: Encrypted State Management **Always Encrypted:** DERO balances are never stored or transmitted in plaintext. All balance operations happen on encrypted data through homomorphic encryption. ## The Encrypted Balance Structure ### The 66-Byte Format Every DERO balance is stored as 66 bytes of encrypted data: ``` โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ Encrypted Balance (66 bytes) โ”‚ โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค โ”‚ Left Commitment (33 bytes) โ”‚ Right Commitment (33 bytes) โ”‚ โ”‚ L = amountร—G + rร—P โ”‚ R = rร—G โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` **Conceptual structure** (the source struct in `cryptography/crypto/algebra_elgamal.go:34-39` has no inline comments โ€” annotations below are docs notes; `Serialize()` is at `algebra_elgamal.go:84-91`): ```go type ElGamal struct { G *bn256.G1 // docs: Pedersen value generator (NewElGamal sets G = global_pedersen_values.G) Randomness *big.Int // docs: blinding scalar (set by RandomScalarFixed during CommitElGamal) Left *bn256.G1 // docs: L = value ร— e.G + r ร— peer_pubkey (33 bytes compressed) Right *bn256.G1 // docs: R = r ร— G_pkg (note: package-level G, a different generator) } // docs: only Left and Right are serialized (66 bytes); G + Randomness are reconstructed func (e *ElGamal) Serialize() (data []byte) { data = append(data, e.Left.EncodeCompressed()...) data = append(data, e.Right.EncodeCompressed()...) return data } ``` > **Note:** The full struct includes `G` (the Pedersen value generator, set from `global_pedersen_values.G`) and `Randomness` (the blinding scalar) fields used during construction, but only `Left` and `Right` are serialized to the 66-byte on-chain representation. The right-commitment generator (`R = r ร— G`) is the package-level `G` declared at `algebra_pedersen.go:29` โ€” distinct from `e.G`. ### What Each Component Represents | Component | Formula | Purpose | |-----------|---------|---------| | **Left (L)** | `amountร—G + rร—P` | Encrypted amount + randomness | | **Right (R)** | `rร—G` | Randomness commitment (for decryption) | **Where:** - `amount` = The actual balance (hidden) - `G` = Pedersen value generator (`global_pedersen_values.G`) โ€” the same `G` used in every value commitment - `r` = Random blinding scalar (secret, from `RandomScalarFixed`) - `P` = Account's public key (used as the second generator inside `L`, not a global `H`) - The `R = r ร— G` term uses a **distinct** package-level `G` (`algebra_pedersen.go:29`) for the randomness commitment โ€” the formula collapses two generators for brevity --- ## Zero Balance Initialization ### The Genesis Rule **From Source Code** (`blockchain/transaction_execute.go:189-194`): ```go // give new wallets generated in initial month a balance // so they can claim previous chain balance safely/securely without revealing themselves // 144000= 86400/18 *30 if globals.IsMainnet() && height < 144000 { zerobalance = zerobalance.Plus(new(big.Int).SetUint64(200)) } ``` ### What This Means | Registration Block | Initial Balance | Reason | |-------------------|-----------------|--------| | **< 144,000** | 200 atomic units | Early adoption period | | **โ‰ฅ 144,000** | 0 DERO | Standard registration | **For context:** - 144,000 blocks = 30 days of 18-second blocks (`86400 / 18 ร— 30`) - This bonus period ended long ago; the vast majority of addresses have zero initial balance **Timeline:** The 200-unit bonus only applied to addresses registered in the first ~30 days of mainnet (before block 144,000). Any address registered after that starts with exactly zero DERO. --- ## Homomorphic Operations ### Addition (Receiving DERO) **When you receive DERO:** ```mermaid flowchart TD A["Your Balance: E(500)"] --> OP["Homomorphic Add"] B["Incoming: E(100)"] --> OP OP --> C["New Balance: E(600)"] Note["Network sees: encrypted blobs
Network learns: NOTHING"] ``` **The Math:** ``` E(balance) = (L_balance, R_balance) E(amount) = (L_amount, R_amount) E(balance) + E(amount) = (L_balance + L_amount, R_balance + R_amount) = E(balance + amount) Result: Still encrypted! No decryption needed! ``` ### Subtraction (Sending DERO) **When you send DERO:** ```mermaid flowchart TD A["Your Balance: E(500)"] --> OP["Homomorphic Subtract"] B["Outgoing: E(100)"] --> OP OP --> C["New Balance: E(400)"] ``` **The Math:** ``` E(balance) + E(-amount) = (L_balance + L_negAmount, R_balance + R_negAmount) = E(balance - amount) ``` > **Implementation note:** there is **no** `Sub` method on `ElGamal` (method set is `Add / Plus / Mul / Neg / Serialize`). The wallet builds a signed `changes` ciphertext at `walletapi/daemon_communication.go:886-887` and the daemon then adds it via `nb.Balance.Add(echanges)` at `blockchain/transaction_execute.go:239`. Subtraction is "add a negated commitment," not a primitive. **Source:** `cryptography/crypto/algebra_elgamal.go:69` (`func (e *ElGamal) Add`) and `:80` (`func (e *ElGamal) Plus`) โ€” these are the two homomorphic primitives; subtraction is composed from `Add` + `Neg`. --- ## What Balance Changes Mean ### When Balance Changes | Scenario | Balance Changes? | Reason | |----------|-----------------|--------| | **Send DERO** | Yes | Subtracted from your balance | | **Receive DERO** | Yes | Added to your balance | | **Ring member (decoy)** | **Yes** | Participates in ring signature | | **No activity** | No | Balance unchanged | ### The Ring Member Case (Critical) **Important:** Encrypted balance changes occur for ALL ring members in a transaction, including decoys. This is by design, not a bug. See [Ring Member Behavior](/integrity/ring-member-behavior.md) for details. **Source** (`walletapi/daemon_communication.go:886-887` โ€” the `//` lines below are docs annotations, not in source): ```go // docs: this runs for every monitored address that appears in the ring, // including decoys โ€” the encrypted blob updates either way. changes := crypto.ConstructElGamal(tx.Payloads[t].Statement.C[j], tx.Payloads[t].Statement.D) changed_balance_e := previous_balance_e_tx.Add(changes) ``` --- ## Balance Query Process ### How to Query Balance ### Encrypted (Anyone) **Query Encrypted Balance (Public)** ```bash curl -X POST http://127.0.0.1:10102/json_rpc \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "getencryptedbalance", "params": { "address": "dero1qy...", "scid": "0000...0000", "topoheight": 1081893 } }' ``` **Response:** ```json { "data": "002a319487393969e9552e6b64176c88...", "registration": 1059301, "bits": 26, "height": 1081893, "status": "OK" } ``` **What you see:** 66 bytes of encrypted data **What you learn:** Nothing about actual balance ### Decrypted (Owner Only) **Decrypt Balance (Requires Private Key)** **Decryption process:** 1. Deserialize the 66-byte encrypted balance into an ElGamal pair (Left, Right) 2. Compute `Left - privateKey ร— Right` which yields `amount ร— G` 3. Solve the discrete log (baby-step giant-step) to recover the integer amount **What you see:** Actual balance (e.g., 500 DERO) **Who can do this:** Only the address owner (requires private key for step 2) ### The Encrypted Balance Identity Test **Comparing balances at different heights:** ``` Block 1,059,301: "002a319487393969e9552e6b64176c88..." Block 1,081,892: "002a319487393969e9552e6b64176c88..." โ† IDENTICAL Block 1,081,893: "a58442215349d55ceaac042821d568c8..." โ† CHANGED ``` **What this tells us:** - Identical encrypted data = No balance change - Different encrypted data = Balance changed (for ANY reason) - 22,592 blocks unchanged = No involvement in any transaction (not even as ring member) --- ## Balance Conservation ### The Conservation Law ```mermaid flowchart TD A["Total Supply"] --> B["Sum of all encrypted balances"] B --> C["Must remain constant"] TX["Every Transaction"] --> D["Sender: -X"] TX --> E["Receiver: +X"] TX --> F["Fee: to miner"] D --> G["Sum: 0 (conserved)"] E --> G F --> G ``` **The homomorphic operations preserve this:** ``` Before: E(sender_balance) + E(receiver_balance) = E(total) After: E(sender_balance - amount) + E(receiver_balance + amount) = E(total) The total is unchanged (minus fee to miner) ``` ### Network Verification **The network verifies conservation without seeing amounts.** Because ElGamal is additively homomorphic, the network can confirm that the sum of encrypted inputs equals the sum of encrypted outputs -- without decrypting any of them. If the encrypted totals don't match, the transaction is rejected. The actual balance updates happen in `blockchain/transaction_execute.go` using the `ElGamal.Add()` operation from `cryptography/crypto/algebra_elgamal.go:69`. --- ## Security Properties ### What's Protected | Property | How It's Achieved | |----------|------------------| | **Balance confidentiality** | ElGamal encryption | | **Balance integrity** | Commitment binding | | **Conservation** | Homomorphic verification | | **Non-negative balances** | Range proofs | ### What's Visible | Information | Visible To | |-------------|-----------| | **Encrypted balance (66 bytes)** | Anyone | | **That balance changed** | Anyone | | **Actual balance value** | Only owner | | **Transaction amounts** | Only sender/receiver | --- ## Key Takeaways ### The Encryption Guarantee **Always Encrypted:** From creation to storage to operations, DERO balances are always encrypted. The network processes all value transfers without ever seeing a single plaintext balance. ### Balance Change Interpretation | Observation | What It Means | What It Doesn't Mean | |-------------|--------------|---------------------| | **Balance unchanged** | Address not involved in ANY transaction | - | | **Balance changed** | Address participated in some transaction | โ‰  Address was sender | | **66 bytes different** | Some balance operation occurred | โ‰  Received or sent specific amount | ### The Homomorphic Advantage ``` Traditional blockchain: Read balance โ†’ See actual amount โ†’ Privacy broken DERO: Read balance โ†’ See encrypted blob โ†’ Privacy preserved Math on encrypted โ†’ Result still encrypted โ†’ Privacy preserved Only owner decrypts โ†’ With private key โ†’ Privacy preserved ``` --- ## Related Pages **Security Suite:** - [Ring Member Behavior](/integrity/ring-member-behavior.md) - Why decoys' balances change - [Negative Transfer Protection](/integrity/negative-transfer-protection.md) - Range proof security **Privacy Suite:** - [Homomorphic Encryption](/privacy/homomorphic-encryption.md) - Full technical details - [Transaction Privacy](/privacy/transaction-privacy.md) - Complete privacy model **Technical Reference:** - [Wallet RPC API](/rpc-api/wallet-rpc-api.md) - Balance queries - [Daemon RPC API](/rpc-api/daemon-rpc-api.md) - GetEncryptedBalance method --- --- title: "The 2022 Inflation Claim: Claims vs. Evidence | DERO Blockchain" description: "Point-by-point technical rebuttal of the October 2022 DERO inflation claim, including circulated report claims, the submitted proof string, and protocol mechanics that bound what is and isn't possible." keywords: ["DERO inflation bug", "2022 exploit", "Derolytics", "payload proofs", "ring signatures", "negative transfer", "DERO security", "blockchain investigation"] date: "2026-05-25" lastUpdated: "2026-05-31" authors: ["DHEBP"] slug: "inflation-claim" canonicalUrl: "https://derod.org/integrity/inflation-claim" tags: ["privacy", "security", "history", "proofs", "ring-signatures", "investigation"] --- # The 2022 Inflation Claim: Claims vs. Evidence _Derolytics' "irrefutable proof" is a string anyone can forge โ€” and even a genuine one describes a transfer the chain would have rejected._ **Scope:** This page tests **one** claim: that DERO minted ~2.2M coins in October 2022 by exploiting a bug in how transfers were validated. Laundering totals, dollar figures, and attribution to individuals all **derive from this single claim** โ€” if it falls, they fall with it. Governance and wallet-holdings allegations are out of scope here. ## TL;DR Summary | Question | The Evidence | |----------|--------------| | **Did total supply increase by ~2.2M DERO?** | **No.** The exploit-block reward was **0.615 DERO** โ€” normal scheduled emission, not millions. The report never shows a supply jump on chain. [Part 4](#verify-supply-at-the-exploit-block) | | Is negative-transfer wraparound possible on consensus? | **No.** Range proofs bind every transfer to a non-negative range; a negative/out-of-range amount cannot produce a verifying proof. [Part 4](#part-4-the-chains-account-at-the-exploit-block) | | Is the circulated payload proof cryptographic evidence of a mint? | **No.** It is a user-supplied **display object**; "Verified" means its own math is consistent, not that consensus accepted it. [Part 3](#part-3-forge-a-fake-proof-yourself) | | Can explorer **Verified** on inflated proofs be reproduced? | **Yes** on unpatched explorers (`MAX_INT64_SAFE` bypass). [Part 3](#part-3-forge-a-fake-proof-yourself) | | Does the deanonymization support the ~2.2M? | **No โ€” it refutes it.** The figure is the forgeable proof string, not a deanonymization output. Read the chain directly and what you see is an **ordinary transfer of coins the sender already held**. [Part 5](#part-5-what-deanonymization-can-and-cannot-establish) | | **Bottom line on the keystone?** | **The artifact at the center of every accusation is a display object anyone can forge โ€” and consensus could not have accepted the transfer it depicts.** [Part 6](#part-6-the-keystone-collapses) | --- At the center of every inflation accusation is a string. About a hundred characters of base32, prefixed `deroproof1...`, pasted into an unpatched DERO explorer where it lights up as **Verified โœ“** for an amount the explorer renders as `184,467,438,537,095.51434 DERO` โ€” roughly fourteen million times the entire DERO supply. That string is the foundation of the [Derolytics "DERO Heist" report](https://web.archive.org/web/20250903162339/https://derolytics.com/) and its follow-ups โ€” the source of the **2.2-million-DERO** figure, the cited evidence for every downstream claim of laundering, theft, and attribution. It is also a *payload proof*: a wallet-side display object the protocol gives no third party any way to verify. By design. Ring signatures rely on exactly this ambiguity โ€” if outsiders could verify payload proofs, plausible deniability would die with them. The technique that produced it became possible in **May 2024**, when a separate wallet-layer randomness-reuse bug (patched in Release 142) gave outside observers their first means of reading inside DERO's encrypted payloads. Pointed back at a transaction mined on **October 17, 2022** โ€” accepted by every validating node, indistinguishable on-chain from any other transfer โ€” that technique returned a value, paired it with a payload proof, and announced an inflation. The chain never said any such thing. The transaction is the same one it has always been: bounded by range proofs that pin every amount to a non-negative range, conserved by balance proofs that bind inputs to outputs, accepted unanimously. What changed in 2024 was the ability to *interpret* โ€” and a misreading, intentional or otherwise, of what a payload proof is and does. The entire Derolytics narrative rests on that single misreading. Every chart, every accusation, every dollar figure. --- ## Part 1: The Claim and Its Foundation The report cites this **payload proof** as cryptographic evidence โ€” readers paste it into an explorer, see **Verified**, and treat that as confirmation the on-chain transfer was negative ([Proof Types](/integrity/payload-vs-transaction-proofs.md); display-layer only, not consensus). As cited: ``` Payload proof: deroproof1qyyj0cgu3htmkumr79sgca75vwsx8kx7zkrjg0nfez46w36qyx4kwq9zvfyyskpqvdpcfhkhk4m7y9d77ehyj7yhnnrv9z0tjr9m5fqe2yx9t27dwtdxy4j4r0llll7vcmaxwjcl8jzfq Date: October 17, 2022 Block: 1,081,893 TX: 5bbe1b7eecfe3447cb045b1197a07a214b456968eda8a3d5a90f5fae9ce57e55 ``` **Category error:** **Verified** on a pasted payload proof means the display object's internal math is consistent โ€” **not** that nodes accepted the transfer or minted coins. Payload proofs are user-supplied; explorers check math, not consensus. [Proof Types](/integrity/payload-vs-transaction-proofs.md) ```mermaid flowchart TD subgraph display["Display layer โ€” payload proofs"] D1["Paste deroproof into explorer"] D2["Explorer runs commitment math"] D3["Verified โœ“ + on-screen amount"] D1 --> D2 --> D3 end subgraph consensus["Consensus layer โ€” transaction proofs"] C1["Wallet broadcasts signed transaction"] C2["Every node verifies sigma + range proofs"] C3["Tx mined in block โ†’ chain state updated"] C1 --> C2 --> C3 end D3 -->|"Report treats as"| CLAIM["Proof of ~2.2M mint"] C3 -->|"Actually governs"| FACTS["Supply curve + block reward"] ``` **The technical claim** (as stated in public exploit reports) rests on a single assumption โ€” that the payload proof above is cryptographic evidence, and what verifies on an explorer also represents what consensus accepted: 1. The transfer amount was **โˆ’2,200,000.00181 DERO** โ€” `โˆ’220,000,000,181` atoms when the bech32 is decoded ([Part 2](#part-2-the-explorer-wraparound--what-it-actually-proves)). 2. Stored as `uint64` (an unsigned 64-bit integer, no negatives), that negative value wraparound displays as **~184 trillion DERO** on explorers โ€” roughly **14 millionร— total supply**. 3. Post-2024 deanonymization is cited to name a fresh wallet as the **sender** โ€” and to read the wraparound as a **~2.2M DERO** credit to that sender, not the **~184 trillion** figure on screen. 4. **Conclusion:** consensus failed โ†’ **~2.2M DERO** minted from nothing. Each step is load-bearing. The rest of this page evaluates them on three independent grounds โ€” the proof string ([Parts 2โ€“3](#part-2-the-explorer-wraparound--what-it-actually-proves)), what consensus enforces ([Part 4](#part-4-the-chains-account-at-the-exploit-block)), and attribution limits ([Part 5](#part-5-what-deanonymization-can-and-cannot-establish)) โ€” then synthesizes them ([Part 6](#part-6-the-keystone-collapses)). ### Report claims vs. evidence | Report claim | What actually follows | |---|---| | *"Protocol failed to validate transaction proofs"* | They mean **payload proofs** (display layer). **Transaction proofs** are verified by every node. [Proof Types](/integrity/payload-vs-transaction-proofs.md) | | *"Verify yourselfโ€ฆ proof string โ€ฆ on the official explorer"* | **Verified** = pasted object math checks out, not node acceptance. The string decodes to exactly **โˆ’2,200,000.00181** and the explorer's display-layer consistency check passes โ€” because that is all a display proof does. [Part 3](#part-3-forge-a-fake-proof-yourself) | | *"Sender actually received 2.2M DERO"* | The ~2.2M is the [forgeable proof string](#part-3-forge-a-fake-proof-yourself), not a deanonymization result. Read the chain directly and what you see is an **ordinary transfer of coins the sender already held**. [Part 5](#part-5-what-deanonymization-can-and-cannot-establish) | | *"Both wallets freshly created and empty"* | Ring members **always** show encrypted balance changes โ€” including decoys who did not send. [Ring Member Behavior](/integrity/ring-member-behavior.md) | | *"$8.34M laundered over 781 transactions"* | **Assumes the mint happened.** No keystone โ†’ the graph is unmotivated. Out of scope here. | --- ## Part 2: The Explorer Wraparound โ€” What It Actually Proves Paste the [Part 1](#part-1-the-claim-and-its-foundation) **payload proof** into an unpatched explorer and it displays **`184,467,438,537,095.51434 DERO`** with **Verified โœ“** โ€” roughly **14 millionร— total supply** on screen. That figure is a display-layer reading of the embedded `uint64` as a positive number. **Proves:** Unpatched explorers can mark inflated payload proofs **Verified** โ€” including amounts that bypass `MAX_INT64_SAFE` and wrap to negatives. **Does not prove:** The on-chain transaction contained that amount. [Remediation](#part-6-the-keystone-collapses) **The proof is authentic.** Decode the bech32 string as an integer (`rpc.NewAddress` โ†’ `args.Value(RPC_VALUE_TRANSFER, DataUint64)`) and the embedded value is `18,446,743,853,709,551,435` โ€” exactly **โˆ’2,200,000.00181 DERO**, the report's own stated figure to the atom. The "off-by-one" in the display is the explorer's rounding, not a flaw in the proof: `FormatMoneyPrecision` parses the `uint64` via `big.ParseFloat(..., prec=0, ...)`, which Go's stdlib promotes to a **64-bit mantissa** before rounding (documented behavior โ€” when `prec=0`, [`math/big.Float.Parse`](https://pkg.go.dev/math/big#Float.Parse) sets it to 64). At that precision the step size near 10ยนโด (~`0.0000153 DERO`) is *just over* one atomic unit (`0.00001 DERO`), so rounding lands in the **last** place โ€” `โ€ฆ51435` renders as `โ€ฆ51434`. Authenticity is the page's point, not a problem for it. The misreading at the heart of the inflation claim isn't "Derolytics produced a broken proof" โ€” it's that an authentic display object was treated as consensus state. A layer that cannot reliably render its own last digit is not consensus state. ### Decode it yourself The canonical path the callout cites โ€” `rpc.NewAddress` โ†’ `args.Value` โ€” runs in ~10 lines against any DEROHE checkout: ```go // go run decode.go โ€” requires a DEROHE checkout. package main import ( "fmt" "github.com/deroproject/derohe/rpc" ) func main() { addr, _ := rpc.NewAddress("deroproof1qyyj0cgu3htmkumr79sgca75vwsx8kx7zkrjg0nfez46w36qyx4kwq9zvfyyskpqvdpcfhkhk4m7y9d77ehyj7yhnnrv9z0tjr9m5fqe2yx9t27dwtdxy4j4r0llll7vcmaxwjcl8jzfq") v := addr.Arguments.Value(rpc.RPC_VALUE_TRANSFER, rpc.DataUint64).(uint64) fmt.Printf("uint64: %d\n", v) // 18446743853709551435 fmt.Printf("signed: %d atoms\n", int64(v)) // -220000000181 fmt.Printf("DERO: %.5f\n", float64(int64(v))/100_000) // -2200000.00181 } ``` On the cited TX with the [Part 1](#part-1-the-claim-and-its-foundation) string: **Unpatched** ([DEROFDN/derohe `main`](https://github.com/DEROFDN/derohe/tree/main) โ€” no `proof/proof_validation.go`) shows it as **Verified โœ“**: ![Unpatched explorer displays the report proof as Verified โ€” 184,467,438,537,095.51434 DERO](/assets/integrity/inflation-claim/explorer-unpatched-report-verified.png) **Patched** ([DEROFDN/derohe `community-dev`](https://github.com/DEROFDN/derohe/tree/community-dev), via [PR #14](https://github.com/DEROFDN/derohe/pull/14) โ€” `ValidatePayloadProofAmount`) rejects the wraparound before display: ![Same report proof rejected by the patched explorer](/assets/integrity/inflation-claim/explorer-patched-report-rejected.png) [Part 3](#part-3-forge-a-fake-proof-yourself) shows anyone can forge such proofs for arbitrary amounts. --- ## Part 3: Forge a Fake Proof Yourself **We forged one to show how trivial it is.** Below is a fake `deroproofโ€ฆ` built specifically for this page โ€” accepts on unpatched explorers, shows an amount that never moved on-chain. It took minutes. No wallet, no private keys, no insider access. Everything needed is already public: the [Part 1](#part-1-the-claim-and-its-foundation) transaction, its 16 ring slots, and the commitment math. The point isn't that forgery is *theoretically possible* โ€” it's that **the report's "Verified โœ“" evidence is the same kind of object, built the same way**. ### The trick, in plain English 1. **Pick the real transaction** everyone is looking at (`5bbe1b7eecfe3447cb045b1197a07a214b456968eda8a3d5a90f5fae9ce57e55`). 2. **Pick one of 16 ring slots** (positions 0โ€“15) โ€” each slot has a public address; you choose which slot the fake proof should attach to. 3. **Pick any amount** you want on screen โ€” including **โˆ’1 DERO** or **~184 trillion DERO** wraparound values. 4. **Do the math.** Each ring slot has a published commitment of the form `amount ร— G + blinder` โ€” public on chain. Pick any amount; rearrange to solve for the blinder that fits: `blinder = C[slot] โˆ’ amount ร— G`. 5. **Paste the string** into an unpatched explorer with the same TX. If the display math fits โ†’ **Verified โœ“** on an unpatched explorer. Nodes never saw the string; supply didn't change. The circulated report string ([Part 1](#part-1-the-claim-and-its-foundation)) is exactly one such pasted object. **Three ways to see it for yourself**, easiest first โ€” paste ours, ask an agent, or build one from scratch with nothing but public data. ### Tier 0 โ€” Paste the one we already made **Paste this forged demo** โ€” built for this page, not from the report. | Field | Value | |---|---| | **TX** | `5bbe1b7eecfe3447cb045b1197a07a214b456968eda8a3d5a90f5fae9ce57e55` | | **Ring slot** | **0** (of 16) | | **Encoded amount** | **โˆ’1 DERO** โ†’ renders on screen as `184,467,440,737,094.51616` | ``` deroproof1qyvvfxzyfqtjm0lgyf5jncleh6cxmmfahgmekxpyrzhhsz832dv8qq9zvfyyskpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqxy4j4r0lllllllll8jcq3r0a08 ``` **Unpatched** ([DEROFDN/derohe `main`](https://github.com/DEROFDN/derohe/tree/main)): ![Page-built โˆ’1 DERO forged proof accepted by unpatched explorer](/assets/integrity/inflation-claim/explorer-unpatched-forged-verified.png) **Patched** ([DEROFDN/derohe `community-dev`](https://github.com/DEROFDN/derohe/tree/community-dev), [PR #14](https://github.com/DEROFDN/derohe/pull/14)): ![Same forged proof rejected โ€” wraparound amount blocked](/assets/integrity/inflation-claim/explorer-patched-forged-rejected.png) ### Tier 1 โ€” Ask your agent to forge one (no setup) No Go, no keys, no math. The [DERO MCP server](/tools/mcp-server.md) ships a `dero_forge_demo_proof` tool โ€” connect once, then ask in plain language. Two ways in: - **Nothing to install** โ€” point an HTTP MCP client (ChatGPT custom connectors, Cursor hosted mode) at `https://mcp.derod.org/mcp`. - **Run it yourself** โ€” `npx dero-mcp-server` and add it to Claude or Cursor, or to a privacy-first client like [OpenCode](https://opencode.ai) or [Goose](https://block.github.io/goose) running on a local model via [Ollama](https://ollama.com). Either way it finds a node automatically: your own if you're running one, a public node otherwise. Then ask: > *"Forge a payload proof for TX `5bbeโ€ฆe55`, ring slot 7, for โˆ’5,000,000 DERO."* Back comes a `deroproofโ€ฆ` string. Paste it into an unpatched explorer โ€” it lights up **Verified โœ“**, rendering your โˆ’5M as a ~184-trillion-DERO "mint." The chain never moved a coin. Change the slot, change the amount, go bigger; the "evidence" doesn't care what number you pick โ€” *that's the whole point.* Live now โ€” `npx dero-mcp-server` (v0.4.0+) or the hosted endpoint at `mcp.derod.org/mcp`, both shipping the forge tool and local-first node resolution ([source](https://github.com/DHEBP/dero-mcp-server)). ### Tier 2 โ€” Build one from scratch (no DERO tooling) No wallet โ€” public inputs, public math, one bech32 string. Nothing here comes from DERO, so a skeptic can re-run the whole thing from public data and trust the result. We're showing the work so it can be reproduced, not taken on faith. **What we chose:** ring slot **0**, target **โˆ’1 DERO** (= โˆ’100,000 atoms). Encoded as the `uint64` wraparound **`18446744073709451616`**, the unpatched explorer renders it as a positive number โ†’ **`184,467,440,737,094.51616 DERO`** on screen โ€” the โˆ’1 we picked never appears (same display-layer reading as [Part 2](#part-2-the-explorer-wraparound--what-it-actually-proves)). **The equation** (`proof/proof.go`): ```text amount ร— G + blinder == C[slot] ``` `C[0]` is **public** in the TX hex. Rearrange: **`blinder = C[0] โˆ’ amountร—G`**. That derived point โ€” **not** the ring address โ€” plus `V` (amount) and dummy `H`, bech32-encoded โ†’ demo string above. **Self-check:** ```text proof.Prove(forged, tx_hex, ring, mainnet) โ†’ err=nil โ†’ receiver = dero1qyjgfvvf4e7jrna8xg6mmwh77km6q9nfrgdue6q2lczy33almkgy2qq9wzrkp (slot 0) โ†’ amount = 18446744073709451616 ``` Passes โ†’ unpatched explorer shows **Verified โœ“**. **Nothing on-chain changed.** The circulated report string ([Part 1](#part-1-the-claim-and-its-foundation)) is the same kind of object. ### Fetch the ring (curl) Steps 1โ€“2 โ€” fetch the cited TX and its **16 ring members** (public on-chain): ```bash # Requires a synced mainnet daemon โ€” RPC port 10102 by default. curl -s http://127.0.0.1:10102/json_rpc \ -H 'Content-Type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "DERO.GetTransaction", "params": { "txs_hashes": ["5bbe1b7eecfe3447cb045b1197a07a214b456968eda8a3d5a90f5fae9ce57e55"], "decode_as_json": true } }' | jq '.result.txs[0].ring[0] | length' # List all 16 ring addresses (pick any slot 0โ€“15 for forging): curl -s http://127.0.0.1:10102/json_rpc \ -H 'Content-Type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "DERO.GetTransaction", "params": { "txs_hashes": ["5bbe1b7eecfe3447cb045b1197a07a214b456968eda8a3d5a90f5fae9ce57e55"], "decode_as_json": true } }' | jq -r '.result.txs[0].ring[0] | to_entries[] | "\(.key): \(.value)"' # Raw TX bytes for the Go tab: curl -s http://127.0.0.1:10102/json_rpc \ -H 'Content-Type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "DERO.GetTransaction", "params": { "txs_hashes": ["5bbe1b7eecfe3447cb045b1197a07a214b456968eda8a3d5a90f5fae9ce57e55"] } }' | jq -r '.result.txs_as_hex[0]' > tx.hex # full serialized TX (several KB) โ€” do NOT truncate; the Go tab needs all of it # peek at the start if you like: head -c 80 tx.hex ``` The explorer checks commitment math against these public values โ€” not whether the amount was consensus-valid. ### Pick an amount (Python) Step 3 only โ€” wraparound `uint64` math for a chosen amount. **Does not** output a pasteable `deroproofโ€ฆ` string. ```python # No wallet, no chain access. Pick ANY display amount. ATOMIC = 100_000 UINT64_MOD = 2**64 def forge_wraparound_uint64(negative_dero: float) -> int: negative_atoms = int(round(negative_dero * ATOMIC)) return UINT64_MOD + negative_atoms def uint64_to_display(amount: int) -> float: signed = amount if amount < 2**63 else amount - UINT64_MOD return signed / ATOMIC # Example: forge -1 DERO (the demo callout above) demo = forge_wraparound_uint64(-1.0) whole, frac = divmod(demo, ATOMIC) print(f"uint64 embedded: {demo}") # โ†’ 18446744073709451616 print(f"displays as: {uint64_to_display(demo)} DERO") print(f"explorer raw: {whole:,}.{frac:05d} DERO") # Example: the report's claimed amount claimed = forge_wraparound_uint64(-2_200_000.00181) print(f"\nReport claims: {uint64_to_display(claimed)} DERO") print(f" tail .{int(claimed % ATOMIC):05d} โ€” embedded integer; explorer DISPLAYS .51434 (FormatMoney rounding, see Part 2)") ``` ### Build the string (Go) Step 4 โ€” encode a complete `deroproofโ€ฆ` string. **Building** the proof needs only the TX bytes (to read `C[slot]`); the **ring** is used solely by the optional `proof.Prove` self-check at the end. The proof embeds a **derived blinder point** (`C[slot] โˆ’ amountร—G`) so the explorer math fits โ€” not the ring address string itself. **Setup once.** This imports `github.com/deroproject/derohe/...`, so either drop `forge_demo.go` *inside* a [DEROHE](https://github.com/deroproject/derohe) checkout, or make a folder beside one and wire a module to it: ```bash mkdir forge && cd forge && go mod init forge go mod edit -replace github.com/deroproject/derohe=/path/to/derohe # put forge_demo.go here, then: go mod tidy && go run forge_demo.go ``` ```go // go run forge_demo.go // Self-checks with proof.Prove() โ€” same path as explorer verification. package main import ( "encoding/hex" "fmt" "math/big" "github.com/deroproject/derohe/cryptography/bn256" "github.com/deroproject/derohe/cryptography/crypto" "github.com/deroproject/derohe/proof" "github.com/deroproject/derohe/rpc" "github.com/deroproject/derohe/transaction" ) func main() { txHex := "" // full serialized TX bytes (not the hash) โ€” needed to read C[slot] // Ring is ONLY for the self-check at the bottom. To skip it, leave this empty // and delete the proof.Prove call โ€” building the string does not need it. ring := [][]string{{ "dero1qy...slot0", "dero1qy...slot1", // ...all 16 addresses from the curl tab, in order }} negAtoms := int64(-100_000) // -1 DERO in atomic units โ€” change THIS to pick any amount amount := uint64(negAtoms) // uint64 wrap (two-step form โ€” Go rejects negative-to-uint64 in one constant expression) slot := 0 // ring position 0โ€“15 txBytes, _ := hex.DecodeString(txHex) var tx transaction.Transaction tx.Deserialize(txBytes) Ck := tx.Payloads[0].Statement.C[slot] var amountG bn256.G1 // Two representations, on purpose: the SIGNED value is the curve scalar; the UNSIGNED // wrap (`amount`, embedded as the display Value below) is NOT. Don't "simplify" to // SetUint64(amount) โ€” on the curve 2^64โˆ’k โ‰  โˆ’k, so the proof would stop verifying. amountG.ScalarMult(crypto.G, new(big.Int).SetInt64(int64(amount))) blinder := new(bn256.G1).Set(Ck) blinder.Add(blinder, new(bn256.G1).Neg(&amountG)) p := rpc.NewAddressFromKeys((*crypto.Point)(blinder)) p.Mainnet, p.Proof = true, true p.Arguments = rpc.Arguments{ {Name: "H", DataType: rpc.DataHash, Value: crypto.Hash{}}, {Name: rpc.RPC_VALUE_TRANSFER, DataType: rpc.DataUint64, Value: amount}, } forged := p.String() fmt.Println(forged) receivers, amounts, _, _, err := proof.Prove(forged, txHex, ring, true) fmt.Printf("Self-check: err=%v receiver=%s atoms=%d\n", err, receivers[0], amounts[0]) } ``` Change `amount` and `slot` to forge any display value for any ring position. If `proof.Prove` succeeds, an unpatched explorer would show **Verified โœ“** for that amount. --- ## Part 4: The Chain's Account at the Exploit Block The proof asserts consensus accepted a negative-amount transfer โ€” that the protocol minted ~2.2M DERO from nothing. The chain testifies otherwise on two independent counts. **First:** range proofs cannot verify a negative-amount transfer, so no validating node could have accepted one. **Second:** the block where it allegedly happened records a **0.615 DERO** reward โ€” scheduled emission, not millions โ€” and one transaction whose range proofs passed cleanly at every validator. Both counts hold. ### Negative transfers fail range-proof validation Could negative transfers pass consensus โ€” separate from the submitted proof string? **No โ€” and the guarantee is cryptographic, not a string-parsing quirk.** Every DERO transfer carries a **Bulletproof range proof**. The protocol packs the **transfer amount** and the sender's **remaining balance** into one 128-bit value and proves, in zero knowledge, that it lies in `[0, 2^128)` โ€” i.e. that *both* the amount sent and the balance left over are valid **non-negative** 64-bit numbers (`number := btransfer.Add(btransfer, bdiff.Lsh(bdiff, 64))` at `cryptography/crypto/proof_generate.go:471`). A "negative" transfer is the `uint64` wraparound of a huge value, and it cannot satisfy that proof: - **As the amount** โ€” a value near `2^64` exceeds the 64-bit range bound. - **As the consequence** โ€” spending more than you hold drives the *remaining balance* negative, which wraps out of range too. By the **computational soundness** of Bulletproofs โ€” under the discrete-log assumption on the bn256 curve, in the random oracle model (Fiat-Shamir) โ€” no prover can construct a proof that *verifies* for an out-of-range committed value, except with negligible probability bounded by the underlying hardness. Combined with DERO's homomorphic accounting (inputs and outputs are bound to balance exactly), value cannot be created from nothing. Every node runs this verification independently before accepting a block, so a negative-transfer mint is rejected at **consensus** โ€” not merely discouraged client-side. See [Cryptographic Assumptions](/integrity/transaction-proofs.md#cryptographic-assumptions) for the full assumption stack. | Proves | Does not prove | |---|---| | The **specific** alleged mechanism cannot produce a verifying proof. | No inflation via *any* mechanism. | | Range proofs bind every node's acceptance. | Every historical tx has been audited. | Full derivation: [Negative Transfer Protection](/integrity/negative-transfer-protection.md). That closes the *mechanism* question. The *outcome* question is what the chain permanently recorded at topo 1,081,893 โ€” not what a pasted deroproof displays. ### Verify supply at the exploit block The report's conclusion is that ~2.2M DERO was **minted from nothing** on October 17, 2022 (topoheight **1,081,893**). To support that, it would need to show abnormal coin creation at consensus โ€” a multi-million DERO step in the block itself, or a supply audit against something other than the emission schedule. It publishes neither: only a payload proof string and an interpretation of the **corresponding transaction** ([Part 1](#part-1-the-claim-and-its-foundation)). Scheduled emission is **deterministic** from block height: premine plus block rewards that halve on a fixed schedule (`CalcBlockReward` in `blockchain/transaction_execute.go`). That formula estimates *expected* cumulative supply at any height. **`DERO.GetInfo` reports the same approximation** (`cmd/derod/rpc/rpc_dero_getinfo.go:81-82`: `PREMINE + CalcBlockReward(topoheight) ร— topoheight`, then divided by `100,000` to convert atomic units to whole DERO) โ€” scheduled emission in whole DERO, **not** a UTXO census or balance sum across the ledger. **Burden of proof.** Supply conservation isn't audited โ€” it's built in. Every accepted transaction is bound by range proofs (amounts must be non-negative) and balance proofs (inputs must equal outputs), so cumulative supply at any height is exactly **premine + scheduled block rewards**. `GetInfo.total_supply` reports that schedule, not a UTXO census โ€” and it doesn't need to. To show a 2.2M mint, the report would need a deviation against an independent supply measure, or an accounting discrepancy in the block record. It shows neither. Per-block emission at this era was **0.615 DERO**, and the cited block records exactly that. The independent checks on this case: block-header **reward**, cited-TX **acceptance** (range proofs passed), and the **impossibility** of the alleged mechanism ([above](#negative-transfers-fail-range-proof-validation)). ### Exploit block: what the chain records Independent on-chain checks at topoheight **1,081,893** โ€” query any synced node: | Check | RPC / source | Result | |---|---|---| | Block timestamp | `GetBlockHeaderByTopoHeight` | 2022-10-17 07:58:09 UTC | | Block hash | `GetBlockHeaderByTopoHeight` | `b6bd914f7fb1c79788fe8676c277e58e7bb5a904317afb096b1d2793af9aed13` | | Block reward | `GetBlockHeaderByTopoHeight` | **0.615 DERO** (61,500 atomic units) โ€” normal scheduled emission, not a 2.2M mint | | TX count | `GetBlockHeaderByTopoHeight` | **1** (the cited transaction) | | Cited TX status | `GetTransaction` | **Accepted and mined** โ†’ all range proofs passed at every validating node | | Expected cumulative supply | Emission formula | **~12,946,618 DERO** at this height (schedule only โ€” not a ledger audit) | For context, if a **+2.2M DERO** consensus mint had occurred at this block, expected cumulative supply under the schedule would be **~15,146,618 DERO** instead โ€” but detecting that would require an **independent** supply measure the protocol does not expose via RPC. The report never publishes one. For **this alleged mechanism**, the block record is decisive anyway: a negative-transfer mint would require consensus to accept an impossible amount ([range proofs](#negative-transfers-fail-range-proof-validation)). The TX **was** accepted โ€” under normal protocol rules, with a **0.615 DERO** block reward, not millions. ### Query the chain ```bash # Requires a synced mainnet daemon โ€” RPC port 10102 by default. # See: /basics/running-a-node # 1) Exploit block header โ€” independent on-chain facts (reward, txcount) curl -s http://127.0.0.1:10102/json_rpc \ -H 'Content-Type: application/json' \ -d '{"jsonrpc":"2.0","id":"1","method":"DERO.GetBlockHeaderByTopoHeight","params":{"topoheight":1081893}}' \ | jq '.result.block_header | {topoheight, hash, timestamp, reward, txcount}' # 2) Flagged TX exists in chain โ€” accepted tx means range proofs passed curl -s http://127.0.0.1:10102/json_rpc \ -H 'Content-Type: application/json' \ -d '{"jsonrpc":"2.0","id":"1","method":"DERO.GetTransaction","params":{"txs_hashes":["5bbe1b7eecfe3447cb045b1197a07a214b456968eda8a3d5a90f5fae9ce57e55"]}}' \ | jq '.result.txs[0] | {in_pool, version}' # 3) Optional โ€” GetInfo reports scheduled emission (same formula as Python tab) curl -s http://127.0.0.1:10102/json_rpc \ -H 'Content-Type: application/json' \ -d '{"jsonrpc":"2.0","id":"1","method":"DERO.GetInfo"}' \ | jq '{topoheight, total_supply, height}' ``` Steps 1โ€“2 are the independent checks. Step 3 confirms `GetInfo.total_supply` implements the emission schedule (`PREMINE + CalcBlockReward ร— height`) โ€” **not** a UTXO census. Matching the Python tab means the RPC uses the formula; it does not detect a surreptitious mint. Same RPC methods are available via the [DERO MCP server](/tools/mcp-server.md) (`dero_get_info`, `dero_get_block_header_by_topo_height`). ### Emission formula (Python) ```python # Emission schedule โ€” same model as DERO.GetInfo (not a UTXO census). # Source: config.PREMINE, blockchain/transaction_execute.go (CalcBlockReward) ATOMIC = 100_000 BLOCK_TIME = 18 REWARD_REDUCTION_INTERVAL = 210_000 * 600 // BLOCK_TIME # 7,000,000 BASE_REWARD = (41 * 100_000 * BLOCK_TIME) // 600 # 123,000 atomic/block at genesis era PREMINE = 1_228_125_400_000 # atomic units (Stargate premine accounting) ALLEGED_MINT = 2_200_000 EXPLOIT = 1_081_893 def calc_block_reward(height: int) -> int: return BASE_REWARD >> ((height + REWARD_REDUCTION_INTERVAL) // REWARD_REDUCTION_INTERVAL) def scheduled_supply_dero(topoheight: int) -> float: atoms = PREMINE + calc_block_reward(topoheight) * topoheight return atoms / ATOMIC # --- At the exploit block (schedule context only) --- expected = scheduled_supply_dero(EXPLOIT) print(f"Scheduled supply at exploit block: {expected:>14,.3f} DERO") print(f"If 2.2M had been minted (hypothetical): {expected + ALLEGED_MINT:>14,.3f} DERO") print(f"Block reward at this height: {calc_block_reward(EXPLOIT) / ATOMIC:.3f} DERO/block") print(f" โ†‘ query independently via GetBlockHeaderByTopoHeight โ€” should match") # --- Emission step across the exploit block (~2ร— block reward, not 2.2M) --- step = scheduled_supply_dero(EXPLOIT + 1) - scheduled_supply_dero(EXPLOIT - 1) print(f"\nSchedule change across block ยฑ1: {step:.3f} DERO") # --- Optional: confirm GetInfo implements the same schedule (not a mint audit) --- def getinfo_matches_schedule(topoheight: int, getinfo_supply: int) -> None: scheduled = scheduled_supply_dero(topoheight) print(f"At topo {topoheight:,}:") print(f" Schedule expects: {scheduled:,.3f} DERO") print(f" GetInfo reports: {getinfo_supply:,} DERO (whole DERO, same formula)") print(f" Match confirms RPC uses the schedule โ€” not an independent supply audit.") # Example: getinfo_matches_schedule(topoheight=, getinfo_supply=) ``` Part 4 closes the consensus side: the alleged mechanism cannot pass range-proof validation. The exploit block records a **0.615 DERO** reward โ€” not a multi-million mint โ€” and the cited transaction in [Part 1](#part-1-the-claim-and-its-foundation) was **accepted**, meaning range proofs passed at every validating node. The report never publishes a supply delta against an independent measure. --- ## Part 5: What Deanonymization Can and Cannot Establish [Parts 2โ€“4](#part-4-the-chains-account-at-the-exploit-block) closed the mint question. The report leans on one further capability โ€” deanonymization โ€” to name a beneficiary and trace funds. Applied honestly to this transaction, it does not support the inflation claim. It undercuts it. **The bug was real, and the fix mattered.** The deanonymization in public reports relies on a genuine wallet-layer randomness-reuse vulnerability (disclosed May 2024, fixed in Release 142): payloads were encrypted under a key derived from a **deterministic** blinding scalar feeding a zero-nonce stream cipher, which Release 142 replaced with a per-payload ephemeral key. This page neither disputes the vulnerability nor minimizes the fix. **The ~2.2M is not a deanonymization result.** It is the [circulated proof string](#part-1-the-claim-and-its-foundation) โ€” a forgeable display object ([Part 3](#part-3-forge-a-fake-proof-yourself)) whose embedded `uint64` reads as โˆ’2,200,000.00181 only if you take a wraparound as negative. The report sources the figure there itself: *"use the proof string on the official explorer to confirm."* **A faithful deanonymization reads the chain โ€” and the chain was constrained in advance.** Deanonymizing recovers the value actually committed in the transaction, not a pasted string. Whatever that value is, the range proof already pinned what it *can* be ([Part 4](#part-4-the-chains-account-at-the-exploit-block)): the sender provably **held** the amount and the balances **conserved**. A committed transfer that wraps either way โ€” the on-screen ~184 trillion DERO or the report's signed โˆ’2.2M read as a credit โ€” is impossible: the first exceeds the 64-bit range bound, and the second requires the sender's remaining balance to go negative, which the range proof also forbids ([Part 4](#negative-transfers-fail-range-proof-validation)). So a faithful deanonymization of this transaction recovers an **ordinary transfer of coins that already existed** โ€” not a mint. The payload structure backs this up: in both pre-fix and post-fix wallet code (`walletapi/transaction_build.go`), the only address-bound byte serialized into the payload is the **receiver index** (`witness_index[1]`) โ€” the sender is never written into the payload in either era. What Release 142 changed was the **key derivation**, from the global blinding scalar `r` to a per-payload ephemeral scalar an outside observer can't reconstruct. A faithful read of either era's payload surfaces a receiver index and the committed value โ€” exactly what a deanonymization can return, and nothing more. Attribution to a named individual is the report's own conceded allegation, resting on timing, access, and behavior โ€” not cryptography. The laundering graph inherits that dependency: with no minted 2.2M, there is nothing to launder. --- ## Part 6: The Keystone Collapses Every downstream claim in the public exploit narrative โ€” dollar figures, laundering graphs, "stolen funds," attribution arguments, the framing of a multi-year cover-up โ€” is built on **one load-bearing artifact**: the payload proof pasted above, presented as cryptographic confirmation that the protocol minted 2.2M DERO from nothing. That artifact fails on four independent grounds โ€” in the order established above: 1. **It is only a display object.** [Part 3](#part-3-forge-a-fake-proof-yourself) โ€” a payload proof is user-supplied; anyone can build a **Verified โœ“** one for any amount and any ring slot. 2. **The mechanism is impossible.** [Part 4](#part-4-the-chains-account-at-the-exploit-block) โ€” a negative/wraparound transfer cannot produce a verifying range proof, so no node would accept it at the protocol layer. 3. **No consensus mint recorded.** [Part 4](#verify-supply-at-the-exploit-block) โ€” block reward was **0.615 DERO**, not millions; the cited TX was **accepted** (range proofs passed). `GetInfo` reports scheduled emission, not a UTXO census โ€” it cannot detect a surreptitious mint by itself. The report never publishes a supply delta against any independent measure. 4. **Deanonymization refutes the mint, it doesn't support it.** [Part 5](#part-5-what-deanonymization-can-and-cannot-establish) โ€” the ~2.2M is the forgeable proof string, not a deanonymization output. A faithful deanonymization reads the value committed on-chain, which the range proof guarantees was held and conserved โ€” an ordinary transfer. Attribution to a person is the report's own conceded allegation. The display-layer bug that made this confusion possible was real. It is being remediated โ€” [DEROFDN/derohe `community-dev`](https://github.com/DEROFDN/derohe/tree/community-dev) ([PR #14](https://github.com/DEROFDN/derohe/pull/14)), [HOLOGRAM](https://hologram.derod.org), and patched explorers now reject proofs like this one; `main` and other unpatched explorers may still show **Verified**. That is a display-layer problem worth fixing. It is not evidence that the chain minted coins; the range proofs do not permit it. **"Don't Trust, Verify" โ€” exactly. So verify the chain, not a string someone hands you.** [Derolytics' executive summary](https://web.archive.org/web/20250903162339/https://derolytics.com/) calls the case *"irrefutable"* and tells you to *"verify yourself"* by pasting the proof into an explorer. But a payload proof's **Verified โœ“** only confirms the display object's own math is self-consistent โ€” it never touched consensus. That's not *Don't Trust, Verify* โ€” it's *trust the checkmark.* The string is [forgeable for any amount](#part-3-forge-a-fake-proof-yourself), describing a transfer [consensus could never accept](#part-4-the-chains-account-at-the-exploit-block). **Verify the chain** โ€” run a node, decode the transaction, check the range proofs โ€” and the "mint" disappears. The artifact at the center of every accusation is a display object anyone can forge. The chain neither records the event the report describes nor permits the mechanism it alleges. Every downstream claim โ€” laundering, attribution, dollar figures โ€” requires that artifact to function as cryptographic evidence. It does not. --- ## Related Pages --- --- title: "Negative Transfer Protection: Cryptographic Impossibility | DERO Blockchain" description: "Why negative or uint64-wraparound transfer amounts cannot pass DERO consensus โ€” grounded in Bulletproof range-proof soundness and homomorphic value conservation, not a client-side check." keywords: ["negative transfer", "inflation protection", "DERO security", "bulletproofs", "range proof", "homomorphic encryption", "uint64", "protocol security"] date: "2025-01-20" lastUpdated: "2026-05-25" authors: ["DHEBP"] slug: "negative-transfer-protection" canonicalUrl: "https://derod.org/integrity/negative-transfer-protection" tags: ["security", "proofs", "inflation", "cryptography", "technical"] --- # Negative Transfer Protection **The chain rejects it.** No DERO transaction can transfer a negative amount or create coins from nothing โ€” the network refuses to accept it. The protection isn't a check inside the wallet that a malicious sender could remove; it's enforced by every node, by recomputing the math on every transfer (formally: range-proof soundness + value conservation). ## The claim **DERO consensus cannot accept a transaction that transfers a negative amount or mints value from nothing.** This is a mathematical guarantee, enforced independently by every validating node. Crucially, it does **not** depend on the sender's wallet behaving honestly. A malicious sender controls their own client, so any protection that lived only in proof *generation* could be patched out. The protection lives in proof *verification*, where it cannot. --- ## What every transfer must prove DERO (Stargate) holds account balances as **homomorphic ElGamal ciphertexts**. A transfer never reveals amounts; instead it carries zero-knowledge proofs that constrain what could have happened: 1. A **Sigma proof** binds the transaction together: the sender controls their key, and the encrypted amounts **conserve value** across the statement โ€” what leaves one account enters others, nothing is created. 2. A **Bulletproof range proof** proves the hidden quantities lie in a valid **non-negative** range. The range proof is the one that closes the door on negative transfers. DERO packs **two** quantities into a single 128-bit value and range-proves them together (`cryptography/crypto/proof_generate.go:468-471`): ```go // transfer amount in the low 64 bits, sender's remaining balance in the high 64 bits btransfer := new(big.Int).SetInt64(int64(witness.TransferAmount)) // this should be reduced bdiff := new(big.Int).SetInt64(int64(witness.Balance)) // this should be reduced number := btransfer.Add(btransfer, bdiff.Lsh(bdiff, 64)) // 128-bit value to range-prove ``` The trailing `// this should be reduced` comments are the DERO author's own forensic note in source โ€” flagging that reduction modulo the bn256 group order should be applied to these inputs. They are preserved verbatim here because they carry that authorial signal. So one range proof establishes **both**: - the **amount sent** is a valid non-negative 64-bit number, and - the sender's **remaining balance** is a valid non-negative 64-bit number. **Why both matter:** proving only the amount is non-negative would not stop an overspend. By also proving the *remaining* balance is non-negative, the same proof guarantees you cannot send more than you hold โ€” and cannot manufacture a balance by sending a "negative" amount. --- ## Why a negative transfer cannot produce a valid proof A "negative" amount is just the two's-complement `uint64` wraparound of a value near `2^64`. Fed into the construction, it fails the range proof from **both** directions: | Attack framing | Why the range proof rejects it | |---|---| | Treat the wraparound as the **transfer amount** | A value near `2^64` lies outside `[0, 2^64)` โ€” the low-64 range bound fails. | | Treat it as **receiving** (so your own balance jumps) | The conservation proof forces a matching decrease; the sender's **remaining balance** goes negative โ†’ wraps โ†’ the high-64 range bound fails. | The decisive property is **computational soundness** โ€” under the discrete-log assumption on bn256, in the random oracle model (Fiat-Shamir). A Bulletproof convinces the verifier that the committed value is in range *without revealing it*, and soundness means a prover **cannot construct a proof that verifies** for a value outside the range, except with negligible probability bounded by the underlying hardness. There is no "almost in range," no rounding, no edge case: either a verifying proof exists (value in range) or โ€” modulo that negligible cheating probability โ€” it does not. See [Cryptographic Assumptions](/integrity/transaction-proofs.md#cryptographic-assumptions) for the full stack. **Common misconception โ€” it is *not* the minus sign.** A claim circulates that protection comes from Go's `BigInt.Text(2)` emitting a `'-'` that "breaks the bit loop." That is not the mechanism: - That loop is **proof *generation*** (the sender's wallet), not node verification โ€” an attacker controls it and could change it. - For a real transaction `number = transfer + (balance << 64)` is **positive**, so `Text(2)` produces no `'-'` at all. - The loop is an `if bit == '1' { โ€ฆ } else { โ€ฆ }`; it does not *detect* or *reject* anything โ€” a stray character would simply be treated as a `0` bit. The protection is the **verifier's** Bulletproof check plus homomorphic conservation. The bit decomposition below is just how an *honest* prover builds the proof โ€” it is not the safeguard. --- ## How the bit decomposition actually works For completeness, lines 473โ€“487 of `proof_generate.go` turn `number` into the two vectors a Bulletproof commits to: ```go number_string := reverse("000โ€ฆ000" + number.Text(2)) // binary digits, zero-padded bits := number_string[0:128] // low 128 bits for _, b := range []byte(bits) { if b == '1' { aL = 1; aR = 0 } // aL[i] = the i-th bit else { aL = 0; aR = -1 } // aR[i] = aL[i] โˆ’ 1 (mod group order) } ``` `aL` is the bit vector of `number`; `aR = aL โˆ’ 1`. Note: in the actual source at `proof_generate.go:485`, the `-1` is stored as `new(big.Int).Mod(new(big.Int).SetInt64(-1), bn256.Order)` โ€” i.e. the field-order representative of `-1` (a 256-bit positive integer congruent to `-1` mod `bn256.Order`). A literal `-1` in Go's `big.Int` would carry the negative sign and would *not* be equivalent in the bulletproof's polynomial relations; the `Mod(..., bn256.Order)` is load-bearing. The proof then demonstrates, in zero knowledge, that for every position `aL โˆ˜ aR = 0` and `aL โˆ’ aR = 1` โ€” i.e. **each component really is a single bit (0 or 1)** โ€” and that those bits reconstruct the committed value. A value that is not a genuine 128-bit non-negative integer cannot satisfy those constraints, so the inner-product argument the verifier checks will not close. This is generation code, shown for understanding. What *enforces* the rule is `cryptography/crypto/proof_verify.go`, run by every node: it re-derives the commitments and checks the inner-product relation. A malformed or out-of-range `number` yields a proof that simply fails that check. --- ## Verify it yourself ### Review the source ```bash git clone https://github.com/deroproject/derohe.git cd derohe # The packing + bit decomposition (proof GENERATION) sed -n '466,490p' cryptography/crypto/proof_generate.go # The verification every node runs (the actual ENFORCEMENT) grep -n "func.*Verify" cryptography/crypto/proof_verify.go ``` Look for the `transfer + (balance << 64)` packing and the 128-bit decomposition in `proof_generate.go`, then the inner-product / range check the *verifier* performs in `proof_verify.go`. The safeguard is on the verify side โ€” that is the half an attacker cannot control. ### Try to forge one The honest test is **not** "does `Text(2)` contain a `-`." It is: **can you build a transaction with a negative / wraparound amount whose range proof verifies?** You cannot: - A standard wallet will not assemble such a transfer โ€” the witness is out of range. - Hand-craft a statement with an out-of-range `number`, and `proof_verify.go` rejects the range proof: the inner-product argument does not close. - Every node re-runs that verification before accepting the block, so even a locally forged "acceptance" is rejected by the network. The same holds for the [alleged October 2022 inflation](/integrity/inflation-claim.md): a negative-transfer mint cannot reach consensus. --- ## Why this cannot be bypassed | Layer | Guarantee | |---|---| | **Range proof (Bulletproof)** | Committed transfer **and** remaining balance are provably in `[0, 2^64)`. Soundness โ‡’ no verifying proof exists for an out-of-range value. | | **Homomorphic conservation (Sigma)** | Encrypted inputs and outputs are bound so value is conserved โ€” coins cannot be created, only moved. | | **Independent verification** | Every node re-verifies both proofs before accepting a block. There is no trusted client to subvert. | **Bottom line:** Negative transfers are not blocked by a policy or a parser that could be patched around. They are blocked because no prover can produce a range proof that *verifies* for a negative or out-of-range amount, and because the homomorphic statement conserves value. Minting coins this way is not "hard" โ€” it is cryptographically impossible. --- ## Related Pages **Security suite:** - [Range Proof Integrity](/integrity/range-proof-integrity.md) โ€” how the range proof binds amounts - [Transaction Proofs](/integrity/transaction-proofs.md) โ€” the full proof set every node checks - [Proof Verification Flow](/integrity/proof-verification-flow.md) โ€” end-to-end validation - [2022 Inflation Claim](/integrity/inflation-claim.md) โ€” point-by-point rebuttal of the circulated negative-transfer report **Privacy suite:** - [Bulletproofs](/privacy/bulletproofs.md) โ€” zero-knowledge range proofs --- --- title: "Network Consensus Validation: Distributed Security | DERO Blockchain" description: "How DERO's distributed network validates transactions through consensus - every node verifies independently, creating Byzantine fault tolerance and eliminating single points of failure." keywords: ["network consensus", "distributed validation", "DERO consensus", "Byzantine fault tolerance", "node validation", "blockchain consensus", "transaction finality"] date: "2025-01-20" lastUpdated: "2026-02-06" authors: ["DHEBP"] slug: "network-consensus-validation" canonicalUrl: "https://derod.org/integrity/network-consensus-validation" tags: ["security", "consensus", "network", "validation", "technical"] --- # Network Consensus Validation **Distributed Security:** Every DERO node independently validates every transaction. There's no central authority - security comes from the mathematical certainty that all nodes will reach the same conclusion when given the same data. **Scope of this page:** "Consensus" here refers to *network agreement on transaction validity* โ€” every node independently re-runs the proof system and reaches the same accept/reject decision because the math is deterministic. **Chain consensus** โ€” which sequence of blocks is canonical, how forks are resolved โ€” is a separate concern handled by DERO's proof-of-work + DAG selection rules, and is not the subject of this page. ## The Consensus Model ### Distributed Validation ```mermaid flowchart TD Transaction["Transaction Submitted"] --> N1["Node 1"] Transaction --> N2["Node 2"] Transaction --> N3["Node 3"] Transaction --> N4["Node N..."] N1 --> V1["Verify Proofs"] N2 --> V2["Verify Proofs"] N3 --> V3["Verify Proofs"] N4 --> V4["Verify Proofs"] V1 --> R1{"Valid?"} V2 --> R2{"Valid?"} V3 --> R3{"Valid?"} V4 --> R4{"Valid?"} R1 -->|Yes| A["Accept & Propagate"] R2 -->|Yes| A R3 -->|Yes| A R4 -->|Yes| A R1 -->|No| X["Reject & Drop"] R2 -->|No| X R3 -->|No| X R4 -->|No| X ``` ### Why This Works **Deterministic Verification:** - Same transaction โ†’ Same verification result - Every honest node reaches the same conclusion - No coordination required between nodes - Mathematical certainty, not voting --- ## Transaction Lifecycle ### Phase 1: Submission ```mermaid sequenceDiagram participant W as Wallet participant N as First Node W->>W: Create transaction W->>W: Generate all proofs W->>N: Submit via RPC N->>N: Basic format check alt Format OK N->>N: Queue for full verification else Format Bad N-->>W: Immediate rejection end ``` ### Phase 2: Full Verification **Each node performs complete verification.** The core verification logic lives in `cryptography/crypto/proof_verify.go` in the `Verify()` function (`proof_verify.go:98`). Each node independently runs through the same sequence: 1. **Overflow check** -- Reject if `fees + extra_value` overflows (`proof_verify.go:108-111`) 2. **Parity check** -- Verify the secret parity is well-formed (`proof_verify.go:136-141`) 3. **Polynomial recovery** -- Verify B^w ร— A recovery (`proof_verify.go:162-180`) 4. **Challenge hash** -- Recompute and compare challenge `c` from all six sigma proof components (`proof_verify.go:410-425`) 5. **Inner product** -- Final cryptographic consistency check (`proof_verify.go:457-460`) If any step fails, `Verify()` returns `false` and the transaction is rejected. ### Phase 3: Propagation ```mermaid sequenceDiagram participant N1 as Node 1 participant N2 as Node 2 participant N3 as Node 3 participant NX as Other Nodes N1->>N1: Verify transaction (โœ“) N1->>N2: Propagate transaction N1->>N3: Propagate transaction N2->>N2: Verify transaction (โœ“) N2->>NX: Propagate transaction N3->>N3: Verify transaction (โœ“) N3->>NX: Propagate transaction Note over N1,NX: Invalid transaction is rejected
and NOT propagated ``` **Key Principle:** Nodes only propagate transactions they've independently verified as valid. ### Phase 4: Block Inclusion ```mermaid sequenceDiagram participant MP as Mempool participant M as Miner participant NET as Network MP->>M: Transactions available M->>M: Select valid transactions M->>M: Build block candidate M->>M: Mine (AstroBWT) M->>NET: Announce block NET->>NET: Verify block + ALL transactions alt All Valid NET->>NET: Accept block NET->>NET: Update chain state else Any Invalid NET->>NET: Reject block end ``` --- ## What Gets Verified ### Transaction-Level Checks | Check | What It Validates | Failure Means | |-------|------------------|---------------| | **6 sigma proofs** | A_y, A_D, A_b, A_X, A_t, A_u all valid (A_t includes range proof) | Forged transaction | | **Inner product** | Bulletproof verification (sub-component of A_t range proof) | Invalid amount / proof manipulation | | **Structure** | Valid format, sizes, parity | Malformed TX | | **Overflow** | Fee arithmetic doesn't overflow `uint64` | Arithmetic attack | | **Fee** | Sufficient fee included | Underpaid TX | ### Block-Level Checks | Check | What It Validates | Failure Means | |-------|------------------|---------------| | **All TXs valid** | Every TX passes individual checks | Block contains invalid TX | | **Block header** | Valid previous hash, timestamp | Chain fork or manipulation | | **Mining proof** | Valid AstroBWT solution | Insufficient work | | **Size limits** | Block within size constraints | Oversized block | | **Merkle root** | TX hash tree correct | TX inclusion manipulation | --- ## Byzantine Fault Tolerance ### The Byzantine Generals Problem **DERO's solution:** ```mermaid flowchart TD subgraph "Honest Nodes (Majority)" H1["Honest Node 1
Verifies: Transaction Valid"] H2["Honest Node 2
Verifies: Transaction Valid"] H3["Honest Node 3
Verifies: Transaction Valid"] end subgraph "Malicious Nodes" M1["Malicious Node
Claims: Transaction Invalid"] end H1 --> C["Network agreement:
Transaction is Valid"] H2 --> C H3 --> C M1 --> |"Ignored"| C C --> R["Result: Honest nodes win"] ``` ### Why Malicious Nodes Can't Win **The math is deterministic:** ``` Transaction TX with proofs P For every honest node N: Verify(TX, P) โ†’ Same result If TX is valid: ALL honest nodes accept Malicious nodes saying "invalid" are simply ignored If TX is invalid: ALL honest nodes reject Malicious nodes cannot force acceptance ``` **Key insight:** Nodes don't "vote" on validity. They independently compute the same mathematical result. A malicious node lying about the result is just ignored. --- ## The Verification Timeline ### Single Transaction When a transaction is submitted, it passes through these stages in order: 1. **Basic format check** -- Structural validation (field counts, size limits, parity) 2. **Full proof verification** -- All sigma proofs and inner product proof verified mathematically 3. **Mempool admission** -- If valid, added to the node's mempool 4. **Peer propagation** -- Forwarded to connected peers, who independently verify > **Note:** No official benchmarks exist for per-step verification times. Actual performance depends on hardware, network conditions, and ring size. The codebase does not include benchmark tests for proof verification. ### Block Confirmation **Block Time:** DERO's block time is **18 seconds** as defined in `config/config.go:34`. The README mentions "16s" but this appears to be outdated - the actual constant is `BLOCK_TIME = uint64(18)`. ``` Block time: 18 seconds (from config/config.go) Time 0: TX in mempool Time 18s: Included in block Time 36s: 1 confirmation Time 54s: 2 confirmations Time ~5 min: ~17 confirmations (very secure) ``` **Source verification:** ```go // config/config.go:34 const BLOCK_TIME = uint64(18) const BLOCK_TIME_MILLISECS = BLOCK_TIME * 1000 ``` --- ## Network Topology ### P2P Architecture ```mermaid graph TD N1["Node 1"] --> N2["Node 2"] N1 --> N3["Node 3"] N2 --> N4["Node 4"] N2 --> N5["Node 5"] N3 --> N5 N3 --> N6["Node 6"] N4 --> N7["Node 7"] N5 --> N7 N6 --> N7 ``` **Properties:** - No central coordinator - Multiple paths between nodes - Failure of one node doesn't affect others - Geographic distribution ### TLS Encryption **All node communication is encrypted:** ```go // From p2p/controller.go // Outgoing connections wrap in TLS conntls := tls.Client(conn, &tls.Config{InsecureSkipVerify: true}) // Server generates random TLS certificate tlsconfig := &tls.Config{Certificates: []tls.Certificate{generate_random_tls_cert()}} ``` **Benefits:** - Prevents eavesdropping on transaction data - Encrypts all peer-to-peer traffic **Honest limitations:** - Uses `InsecureSkipVerify: true` -- peers are not authenticated via certificate validation - TLS provides transport encryption, not peer identity verification - Peer identity is established through the DERO handshake protocol, not TLS certificates --- ## Finality ### When is a Transaction "Final"? ### How It Works **Probabilistic Finality:** Like all Proof-of-Work chains, DERO has probabilistic finality -- each additional block confirmation makes reversal exponentially harder. The general principle: - **1 confirmation** -- Transaction is in a block, but a competing chain could still overtake - **More confirmations** -- Each subsequent block multiplies the computational cost of a reversal - **Deep confirmations** -- Reversal becomes economically and computationally impractical The exact reversal probability for any given confirmation depth depends on the attacker's share of total network hashrate. No fixed percentages can be stated without knowing the current hashrate distribution. > **Note:** DERO uses AstroBWT proof-of-work and an 18-second block time (`config/config.go:34`). Specific finality guarantees depend on the live network's hashrate, which varies over time. ### What We Can Say **What the source code defines:** ``` Block time: 18 seconds (config/config.go:34) ``` **Confirmation timing** (simple arithmetic): | Confirmations | Time | |--------------|------| | 1 | ~18s | | 3 | ~54s | | 6 | ~108s (~2 min) | | 10 | ~180s (~3 min) | | 20 | ~360s (~6 min) | How many confirmations to wait is a risk decision for the application or service -- it depends on the transaction value and the current network hashrate, neither of which are protocol constants. ### Block Reorganization ```mermaid graph LR subgraph "Main Chain" B1["Block 1000"] B2["Block 1001"] B3["Block 1002"] end subgraph "Fork (Temporary)" F1["Block 1001'"] F2["Block 1002'"] end B1 --> B2 B2 --> B3 B1 --> F1 F1 --> F2 B3 --> |"Longer chain wins"| MAIN["Main chain continues"] F2 --> |"Orphaned"| ORPHAN["Fork abandoned"] ``` **Reorg protection:** Deeper transactions are safer because reorganizing the chain becomes exponentially harder. --- ## Security Guarantees ### What Consensus Provides | Guarantee | How It's Achieved | |-----------|------------------| | **No fake transactions** | Cryptographic proof verification | | **No transaction replay** | Nonce/height tracking and key image binding to tree state | | **No censorship** | Decentralized mining | | **Eventual finality** | Longest chain rule | | **Consistent state** | Deterministic verification | ### What It Doesn't Provide | Non-Guarantee | Why | |---------------|-----| | **Instant finality** | Probabilistic confirmation | | **Privacy from nodes** | Nodes see encrypted TXs | | **51% attack immunity** | Theoretical possibility | --- ## Key Takeaways ### The Consensus Guarantee ``` Valid transaction + Network propagation = Guaranteed acceptance Because: 1. All honest nodes compute same result 2. Honest nodes only propagate valid TXs 3. Invalid TXs die at first node they reach 4. Majority honest nodes = valid state ``` ### Defense in Depth ```mermaid flowchart TD Transaction["Transaction"] --> W["Wallet: Generate proofs"] W --> N1["Node 1: Verify"] N1 --> N2["Node 2: Verify"] N2 --> N3["Node N: Verify"] N3 --> M["Miner: Include in block"] M --> NET["Network: Verify block"] NET --> FINAL["Finality"] ``` **Multiple layers:** - Wallet creates valid proofs (or TX can't be created) - Each node verifies (or TX is dropped) - Miners include only valid TXs (or block is rejected) - Network verifies blocks (or block is orphaned) **No Single Point of Failure:** DERO's security doesn't depend on any single node, miner, or authority. It depends on the mathematical certainty that honest nodes, running honest code, will all reach the same conclusion about transaction validity. --- ## Related Pages **Security Suite:** - [Transaction Proofs](/integrity/transaction-proofs.md) - What nodes verify - [Proof Verification Flow](/integrity/proof-verification-flow.md) - Detailed verification steps **Technical Reference:** - [Running a Node](/basics/running-a-node.md) - Participate in consensus - [Daemon RPC API](/rpc-api/daemon-rpc-api.md) - Submit transactions --- --- title: "Overflow Protection: Integer Safety | DERO Blockchain" description: "Technical documentation of DERO's integer overflow protection mechanisms that prevent arithmetic attacks on transaction fees and values." keywords: ["overflow protection", "integer overflow", "DERO security", "arithmetic attacks", "fee overflow", "transaction security"] date: "2025-01-26" lastUpdated: "2025-01-26" authors: ["DHEBP"] slug: "overflow-protection" canonicalUrl: "https://derod.org/integrity/overflow-protection" tags: ["security", "overflow", "arithmetic", "technical"] --- # Overflow Protection: Integer Safety **Arithmetic Safety:** DERO includes explicit checks to prevent integer overflow attacks that could manipulate transaction fees or values. These checks are performed during proof verification before any transaction is accepted. ## The Threat: Integer Overflow Attacks ### What is Integer Overflow? Integer overflow occurs when an arithmetic operation produces a value outside the range that can be represented by the data type. In blockchain contexts, this can be exploited to: - **Create tokens from nothing** (if overflow wraps to positive) - **Bypass fee requirements** (if fees overflow to small values) - **Manipulate transaction values** (if sums overflow) ### Example Attack Vector ``` Attacker's Goal: Pay minimal fees while appearing to pay maximum uint64 max value: 18,446,744,073,709,551,615 If fees + extra_value overflows: fees = 18,446,744,073,709,551,610 extra_value = 10 fees + extra_value = 18,446,744,073,709,551,620 = 4 (after overflow!) โ† Attack succeeds! ``` --- ## DERO's Protection Mechanism ### The Overflow Check **Location:** `cryptography/crypto/proof_verify.go:108-111` ```go total_open_value := s.Fees + extra_value if total_open_value < s.Fees || total_open_value < extra_value { // stop over flowing attacks return false } ``` ### How It Works ```mermaid flowchart TD A["Transaction with fees + extra_value"] --> B["Calculate total_open_value"] B --> C{"total_open_value < fees?"} C -->|Yes| D["โŒ OVERFLOW DETECTED
Transaction Rejected"] C -->|No| E{"total_open_value < extra_value?"} E -->|Yes| D E -->|No| F["โœ… No overflow
Continue verification"] ``` ### The Mathematical Principle **For unsigned integers, if `a + b` overflows:** ``` a + b < a (always true after overflow) a + b < b (always true after overflow) ``` **For valid (non-overflowing) addition:** ``` a + b >= a (always true) a + b >= b (always true) ``` This property is exploited to detect overflow without needing arbitrary-precision arithmetic. --- ## Verification: Step-by-Step ### Normal Case (No Overflow) ```go fees := uint64(1000) extra_value := uint64(500) total_open_value := fees + extra_value // = 1500 // Check 1: Is 1500 < 1000? NO // Check 2: Is 1500 < 500? NO // Result: โœ… VALID - no overflow ``` ### Attack Case (Overflow Detected) ```go fees := uint64(18446744073709551610) extra_value := uint64(10) total_open_value := fees + extra_value // = 4 (overflowed!) // Check 1: Is 4 < 18446744073709551610? YES! // Result: โŒ OVERFLOW DETECTED - transaction rejected ``` --- ## Test It Yourself ### Go Verification Program ```bash cat <<'EOF' > /tmp/overflow_test.go package main import ( "fmt" ) func main() { // Normal case fees1 := uint64(1000) extra1 := uint64(500) total1 := fees1 + extra1 fmt.Println("=== Normal Case ===") fmt.Printf("fees: %d, extra: %d, total: %d\n", fees1, extra1, total1) fmt.Printf("total < fees? %v\n", total1 < fees1) fmt.Printf("total < extra? %v\n", total1 < extra1) fmt.Printf("Result: %s\n\n", checkOverflow(fees1, extra1)) // Overflow case fees2 := uint64(18446744073709551610) extra2 := uint64(10) total2 := fees2 + extra2 fmt.Println("=== Overflow Attack Case ===") fmt.Printf("fees: %d, extra: %d, total: %d\n", fees2, extra2, total2) fmt.Printf("total < fees? %v\n", total2 < fees2) fmt.Printf("total < extra? %v\n", total2 < extra2) fmt.Printf("Result: %s\n", checkOverflow(fees2, extra2)) } func checkOverflow(fees, extra uint64) string { total := fees + extra if total < fees || total < extra { return "โŒ OVERFLOW DETECTED - REJECTED" } return "โœ… VALID - no overflow" } EOF go run /tmp/overflow_test.go ``` **Expected Output:** ``` === Normal Case === fees: 1000, extra: 500, total: 1500 total < fees? false total < extra? false Result: โœ… VALID - no overflow === Overflow Attack Case === fees: 18446744073709551610, extra: 10, total: 4 total < fees? true total < extra? false Result: โŒ OVERFLOW DETECTED - REJECTED ``` --- ## Where This Check Occurs ### In the Verification Flow ```mermaid sequenceDiagram participant TX as Transaction participant V as Verifier participant P as Proof System TX->>V: Submit transaction V->>V: Extract fees + extra_value V->>V: Check for overflow alt Overflow detected V-->>TX: โŒ Reject immediately else No overflow V->>P: Continue to proof verification P->>P: Verify all proofs P-->>V: Proof result end ``` ### Position in Code The overflow check happens **early** in the verification process, before expensive cryptographic operations: ```go // proof_verify.go - Verify function func (proof *Proof) Verify(scid Hash, scid_index int, s *Statement, txid Hash, extra_value uint64) bool { // ... initial setup ... // Line 108-110: OVERFLOW CHECK (happens first!) total_open_value := s.Fees + extra_value if total_open_value < s.Fees || total_open_value < extra_value { return false } // ... rest of verification (only if overflow check passes) ... } ``` **Why early?** Checking for overflow before expensive operations: 1. Saves computational resources on invalid transactions 2. Prevents attackers from wasting node resources 3. Fails fast on obviously malicious inputs --- ## Related Protections ### Combined with Other Checks | Check | What It Prevents | Location | |-------|-----------------|----------| | **Overflow check** | Arithmetic manipulation (fee wraparound) | `proof_verify.go:108-111` | | **Bulletproof range proof** (A_t commitment closed by the inner product proof) | Out-of-range values, including negative/wraparound amounts. The A_t commitment and the inner product proof are **one bulletproof gate with two named pieces**, not two separable checks โ€” see [Bulletproofs ยง Inner Product Proof โ€” Closing A_t](/privacy/bulletproofs.md#inner-product-proof--closing-a_t) | A_t commitment: `proof_verify.go` (every node); IP closure: `proof_innerproduct.go:71` + `proof_verify.go:457` | ### Order of Verifier Operations ``` Transaction submitted โ†“ Overflow check (this page) โ†“ Proof structure validation โ†“ Parity check โ†“ Sigma proof verification (A_y, A_D, A_b, A_X, A_t, A_u) โ†“ Bulletproof gate (A_t commitment + IP recursive closure) โ†“ โœ… Transaction accepted ``` > The verifier runs these steps sequentially; each is a precondition for proceeding to the next. They are **not** "layers of defense in depth against the same attack" โ€” each catches a different malformation. The cryptographic guarantee against negative-transfer / wraparound mints is the bulletproof gate alone. --- ## Security Guarantees ### What This Protects Against | Attack | How It's Blocked | |--------|-----------------| | **Fee overflow** | Sum comparison catches wraparound | | **Value manipulation** | Early rejection before processing | | **Resource exhaustion** | Fails fast, minimal computation | ### Confidence Level **Mathematical Certainty:** The overflow check uses a fundamental property of unsigned integer arithmetic that cannot be bypassed. If `a + b` overflows, then `a + b < a` is **always** true. This is guaranteed by the Go language specification, which defines `uint64` arithmetic as wrapping modulo 2^64. --- ## Key Takeaways ### The Protection Summary ``` Overflow attack attempt: fees + extra_value overflows โ†“ total < fees (true due to wraparound) โ†“ Check detects overflow โ†“ Transaction REJECTED โ†“ Attack FAILED ``` ### Why This Matters - **Prevents token creation** from arithmetic manipulation - **Protects fee integrity** ensuring miners receive proper fees - **Fails fast** saving network resources - **Language-spec-guaranteed** โ€” Go defines `uint64` arithmetic as wrapping modulo 2^64 --- ## Source Code Reference **File:** `cryptography/crypto/proof_verify.go` **Lines:** 108-111 **Function:** `Verify()` (defined at `proof_verify.go:98`) ```go // The complete overflow protection check total_open_value := s.Fees + extra_value if total_open_value < s.Fees || total_open_value < extra_value { // stop over flowing attacks return false } ``` **Verification command:** ```bash git clone https://github.com/deroproject/derohe.git cd derohe sed -n '108,110p' cryptography/crypto/proof_verify.go ``` --- ## Related Pages **Security Suite:** - [Negative Transfer Protection](/integrity/negative-transfer-protection.md) - Verifier-enforced bulletproof soundness - [Range Proof Integrity](/integrity/range-proof-integrity.md) - 128-bit range proof closed at the verifier - [Proof Verification Flow](/integrity/proof-verification-flow.md) - Complete verification process **Technical Reference:** - [Transaction Proofs](/integrity/transaction-proofs.md) - Proof system overview - [Network Consensus](/integrity/network-consensus-validation.md) - Distributed validation --- --- title: "Proof Types Explained: Transaction vs. Payload Proofs | DERO Blockchain" description: "Critical distinction between DERO's two proof systems - transaction proofs (consensus-level, secure) and payload proofs (display-level, by design unverifiable). Includes technical analysis of fake proof creation and explorer mitigation." keywords: ["transaction proofs", "payload proofs", "DERO proofs", "proof verification", "proof types", "wallet proofs", "consensus proofs", "fake proofs", "int64 wraparound", "explorer validation"] date: "2025-01-20" lastUpdated: "2026-02-06" authors: ["DHEBP"] slug: "payload-vs-transaction-proofs" canonicalUrl: "https://derod.org/integrity/payload-vs-transaction-proofs" tags: ["security", "proofs", "privacy", "verification", "technical"] --- # Proof Types Explained **Critical Distinction:** DERO has two completely different proof systems that serve different purposes. Confusing them leads to fundamental misunderstandings about what can and cannot be verified. A transaction proof is part of the chain, verified by every node. A payload proof is a sender-supplied display string that DERO's own code calls a helper *"to detect and decode output amount for the tx."* It was built to read transactions, not to prove them, which is why it's fakeable by design. ## The Two Proof Systems ```mermaid flowchart TD subgraph "Transaction Proofs (Consensus Level)" TP["Generated by wallet"] TP --> TV["Verified by ALL nodes"] TV --> TC["Cryptographically secure"] TC --> TA["Cryptographically bound"] end subgraph "Payload Proofs (Display Level)" PP["Generated by sender"] PP --> PV["Verified by explorer/wallet"] PV --> PC["Math consistency only"] PC --> PA["Forgeable (commitment-rearrangement)"] end ``` ### Quick Comparison | Aspect | Transaction Proofs | Payload Proofs | |--------|-------------------|----------------| | **Purpose** | Consensus validation | Display/communication | | **Verified by** | All network nodes | Explorer/wallet UI | | **Security** | Cryptographically secure | Math check only | | **Can be faked?** | Computationally infeasible | Yes (commitment-rearrangement) | | **Affects blockchain?** | Yes | No | | **Third-party verifiable?** | Yes (validity only) | No | --- ## Transaction Proofs: The "Real" Proofs ### What They Are Transaction proofs are the cryptographic proofs that make transactions valid. They're generated when you create a transaction and verified by every node on the network. **Components:** - Six Sigma proofs (A_y, A_D, A_b, A_X, A_t, A_u) - Inner product proof - Challenge hash binding all components ### How They Work ```mermaid sequenceDiagram participant W as Wallet participant N1 as Node 1 participant N2 as Node 2 participant N3 as Node 3 W->>W: Generate proofs W->>N1: Submit transaction N1->>N1: Verify all proofs N1->>N2: Propagate if valid N2->>N2: Verify all proofs N2->>N3: Propagate if valid N3->>N3: Verify all proofs Note over N1,N3: ALL nodes verify independently Note over N1,N3: Invalid proofs = transaction rejected ``` ### Security Guarantees **Verification** (see `cryptography/crypto/proof_verify.go`): The `Verify()` function (`proof_verify.go:98`) recomputes the challenge hash `c` from all six recovered sigma components (A_y, A_D, A_b, A_X, A_t, A_u) at lines 410-425, then verifies the inner product proof at lines 457-460. If any component was tampered with, the recomputed hash won't match and `Verify()` returns `false`. **Why they can't be faked:** - All proofs are cryptographically bound - Faking one changes the hash - Changed hash invalidates all responses - Network consensus requires valid proofs --- ## Payload Proofs: Display Convenience ### What They Are Payload proofs are **wallet-level tools** for showing transaction details in explorers and wallets. They're NOT used for consensus - they're just for display. **Purpose:** - Show transaction amounts in explorer - Verify receipt of funds - Sender/receiver communication ### How They Work ```mermaid flowchart TD S["Sender creates transaction"] --> P["Includes payload data"] P --> BC["Transaction on blockchain"] BC --> E["Explorer reads payload"] E --> V["Validates math consistency"] V --> D["Displays amount to user"] Note["Note: This is display only!
Not consensus verification"] ``` ### The Math Check **What payload proof verification actually checks:** The verification in `proof/proof.go` performs a scalar multiplication to check math consistency: it takes the commitment `C[position]`, subtracts a shared key derived from the proof, and checks whether the result equals `amount ร— G`. If the math is consistent, the amount is displayed. The critical detail: this uses `ScalarMult(crypto.G, new(big.Int).SetInt64(int64(amount)))` at line 89 -- the `int64` cast is where the wraparound issue occurs (see [Technical Cause](#technical-cause-the-int64-cast-issue) below). **What this does NOT check:** - โŒ Whether the sender actually had that amount - โŒ Whether the sender is who they claim to be - โŒ Whether the proof was generated legitimately - โŒ Whether the amount is real vs. fabricated --- ## Why fakeability isn't a flaw **Unforgeability is a deliberate property, not a default.** Building it in requires cryptographic binding (signatures or commitments tied to keys), verification by a trusted party (consensus), and a formal soundness argument. DERO's designers added that machinery where the threat model required it โ€” transaction proofs going to chain state. Payload proofs are a sender-supplied helper for *reading* what was sent; their threat model doesn't require unforgeability, so it wasn't built in. The absence isn't a flaw โ€” it's the natural shape of an object whose use case never demanded the property. Treating an object as if it should have a property it was never designed to have โ€” for example, citing a "Verified โœ“" payload proof as evidence of an on-chain mint โ€” is a category error, not a finding. ### How forgery works **Anyone can create a payload proof for any ring member:** ``` Transaction has ring: [Addr_0, Addr_1, ..., Addr_15] Amount: 100 DERO For ANY position (0-15), you can create a proof that says: "Address at position X sent 100 DERO" The math will check out because: - All ring members use the SAME amount in commitments - The commitment math is public - You can solve for any position ``` For the worked example (with the actual fake string, screenshots, and reproducible code), see [Forge a Fake Proof Yourself](/integrity/inflation-claim.md#part-3-forge-a-fake-proof-yourself). ### Demonstration **From security research (August 2025):** ``` Transaction: c4fbc0d541c40abf6f5c818f3a0f8430e3ebb5c3f0811d74a4318892be4a4632 Fake proof created showing: 184,467,436,737,095 DERO (184 trillion) Official DERO explorer result: "โœ“ Proof Verified Successfully" Reality: DERO's emission model targets ~10.5 million total from mining (source: transaction_execute.go:57 comment + CalcBlockReward halving schedule) Conclusion: Payload proofs can show impossible amounts ``` **This is not a bug โ€” it's the consequence of an object built to read, not to prove.** > *The TX above (`c4fbc0d5โ€ฆ`) is an independent security-research example. The forgery walkthrough used throughout the rest of this suite โ€” including the reproducible Go code, the bech32 decode, and the patched-vs-unpatched explorer screenshots โ€” is built around a different transaction (`5bbe1b7eโ€ฆ`) and lives at [Inflation Claim ยง Part 3 โ€” Forge a Fake Proof Yourself](/integrity/inflation-claim.md#part-3-forge-a-fake-proof-yourself). Both transactions illustrate the same phenomenon: a payload proof is a user-supplied display object, not consensus state.* --- ## Technical Cause: The int64 Cast Issue ### Why Fake Proofs "Validate" The ability to create fake proofs showing impossible amounts (like 184 trillion DERO) stems from a specific technical issue in the explorer's proof verification code. **From Source Code** (`proof/proof.go:89`): ```go // Original code - vulnerable to wraparound x.ScalarMult(crypto.G, new(big.Int).SetInt64(int64(amount))) // โ†‘ This cast is the issue ``` **The Problem:** | Input (uint64) | After int64 Cast | Result | |----------------|------------------|--------| | `100` | `100` | โœ… Normal | | `2,200,000` | `2,200,000` | โœ… Normal | | `9,223,372,036,854,775,808` (2^63) | `-9,223,372,036,854,775,808` | โŒ Wraps negative | | `18,446,744,073,707,351,616` | `-2,200,000` | โŒ Wraps to -2.2M | **What Happens:** ```mermaid flowchart TD A["Attacker creates proof with
amount = 18446744073707351616"] --> B["Explorer casts to int64"] B --> C["Value wraps to -2,200,000"] C --> D["Commitment math calculated
with wrapped value"] D --> E["Math 'checks out'
(wrong math, but consistent)"] E --> F["Explorer displays:
'โœ“ Proof Verified'
'Amount: 184 trillion DERO'"] ``` ### Why This Doesn't Affect Protocol Security **Protocol Is Secure:** This issue only affects explorer DISPLAY. The actual transaction proofs (consensus level) are enforced by bulletproof soundness โ€” the verifier rejects any committed value outside the proven range, including negative/wraparound amounts. See [Negative Transfer Protection](/integrity/negative-transfer-protection.md) for the mathematical proof. | Layer | Affected? | Why | |-------|-----------|-----| | **Transaction Proofs** | โŒ No | Bulletproof soundness rejects out-of-range commitments | | **Network Consensus** | โŒ No | All nodes verify with proper validation | | **Blockchain State** | โŒ No | Fake proofs don't affect state | | **Explorer Display** | โœ… Yes | Was showing fake amounts as "verified" | --- ## Explorer Mitigation ### The Fix To prevent explorers from displaying obviously fake amounts, validation was added to the payload proof verification. **Where this lives:** [Hologram's proof validation page](https://hologram.derod.org/proof-validation), and โ€” since [PR #14](https://github.com/DEROFDN/derohe/pull/14) landed โ€” [DEROFDN/derohe `community-dev`](https://github.com/DEROFDN/derohe/tree/community-dev). The upstream `main` branch and other unpatched explorers do not include this validation. Hologram is an official community project developed by DHEBP. **New Validation** (`proof/proof_validation.go`): ```go const ( // Maximum safe value for int64 conversion (2^63 - 1) MAX_INT64_SAFE = 9223372036854775807 // Maximum reasonable amount (22M DERO in atomic units) // ~5% above hard cap, allows buffer while blocking impossible amounts MAX_REASONABLE_AMOUNT_ATOMIC = 22_000_000_000_000 ) func ValidatePayloadProofAmount(amount uint64) error { // Check 1: Prevent int64 wraparound if amount > MAX_INT64_SAFE { return fmt.Errorf("amount exceeds int64 maximum - possible wraparound attack") } // Check 2: Reject impossibly large amounts if amount > MAX_REASONABLE_AMOUNT_ATOMIC { return fmt.Errorf("amount exceeds reasonable maximum - likely fake proof") } return nil } ``` **Fixed int64 Cast** (`proof/proof.go:89`): ```go // Before (vulnerable): x.ScalarMult(crypto.G, new(big.Int).SetInt64(int64(amount))) // After (safe): x.ScalarMult(crypto.G, new(big.Int).SetUint64(amount)) ``` ### What This Prevents | Attack | Before Fix | After Fix | |--------|------------|-----------| | **184 trillion DERO proof (wraparound display)** | โœ“ "Verified" | โœ— "Possible wraparound attack" | | **Negative amount wrapping to large positive (e.g., โˆ’1 DERO โ†’ 184 trillion display)** | โœ“ "Verified" | โœ— "Possible wraparound attack" | | **Legitimate 1M DERO** | โœ“ "Verified" | โœ“ "Verified" | ### Honest Limitations **What This Cannot Prevent:** The fix blocks egregious fakes (184 trillion, negative wraparound) but cannot detect subtle fakes. A fake proof claiming 1,500 DERO instead of 1,000 DERO would still pass validation. This is a fundamental limitation of privacy-preserving design - full verification would require private keys. **What the fix CAN do:** - โœ… Block amounts large enough to trigger `int64` wraparound (the actual demonstrated attack) - โœ… Block amounts that would wrap from negative back to an enormous positive display - โœ… Prevent the specific attack used to create false narratives - โœ… Improve user experience (no impossible amounts displayed) **What the fix CANNOT do:** - โŒ Verify the proof is genuine (would break privacy) - โŒ Detect subtle inflation (e.g., 50% fake) - โŒ Prove sender identity (by design) - โŒ Replace proper wallet verification **The Bottom Line:** This fix is a **defense-in-depth enhancement** for the display layer. It blocks the most egregious fake proofs while acknowledging that payload proofs are fundamentally forgeable as currently constructed โ€” the commitment-rearrangement trick lets any ring member's commitment match any amount. For real verification, users should always check their wallet balance with their private keys. --- ## The Critical Difference ### What Each Proves ### Transaction Proofs **Transaction Proofs Prove:** ``` โœ“ Transaction is valid โœ“ Proofs are cryptographically correct โœ“ Combined 128-bit value is valid (transfer + remaining balance) โœ“ No transaction replay (nonce/height + key image binding) โœ“ Sender has private key Does NOT prove: โœ— Which ring member is sender โœ— The exact amount (only that it's valid) โœ— Sender identity to third parties ``` ### Payload Proofs **Payload Proofs Prove:** ``` โœ“ Math is consistent (commitment matches) Does NOT prove: โœ— The proof is genuine (vs. fabricated) โœ— The sender is who is claimed โœ— The amount is accurate โœ— Anything about the real transaction Payload proofs are DISPLAY TOOLS, not verification! ``` ### Verification Scope ```mermaid flowchart TD subgraph "Network Consensus" T["Transaction Proofs"] T --> V1["Every node verifies"] V1 --> R1["Accept or reject transaction"] end subgraph "Display Layer" P["Payload Proofs"] P --> V2["Explorer/wallet checks math"] V2 --> R2["Display amount (may be fake!)"] end T -.-> |"Consensus affects"| BC["Blockchain State"] P -.-> |"No effect on"| BC ``` --- ## Implications ### For Users **When viewing transaction details:** - โœ… Transaction existence is real (on blockchain) - โœ… Ring members are real (from blockchain) - โš ๏ธ Displayed amounts may not be accurate - โš ๏ธ Sender attribution may be wrong **To verify you received funds:** - โœ… Check your wallet balance (decrypted with your key) - โŒ Don't rely solely on explorer display ### For Developers **When building on DERO:** - โœ… Trust transaction proof validity (consensus level) - โŒ Don't trust payload proof amounts (display level) - โœ… Use wallet RPC to get real balances - โŒ Don't use explorer proofs for verification logic ### For Analysts **When analyzing transactions:** - โš ๏ธ Payload proofs can be fabricated - โš ๏ธ Sender attribution is not cryptographically verifiable - โš ๏ธ Amounts shown may be manipulated - โœ… Transaction existence/validity is verifiable --- ## Key Takeaways ### Transaction Proofs | Aspect | Status | |--------|--------| | **Purpose** | Consensus validation | | **Verified by** | All network nodes | | **Can be faked** | No | | **Trust level** | Cryptographically secure | ### Payload Proofs | Aspect | Status | |--------|--------| | **Purpose** | Display convenience | | **Verified by** | Explorer/wallet UI | | **Can be faked** | Yes (commitment-rearrangement) | | **Trust level** | Math check only | ### The Bottom Line ``` Transaction Proofs = "Is this transaction valid?" (consensus) Payload Proofs = "What does the sender claim?" (display) Transaction proofs affect the blockchain. Payload proofs are just metadata for display. Don't confuse the two! ``` --- ## Related: Payload Encryption (Separate Issue) **Distinct from payload proofs:** This page covers payload *proofs* (display-level, fakeable due to the commitment-rearrangement construction). A separate issue involving payload *encryption* was disclosed in May 2024 and fixed in Release142. The payload encryption issue involved **randomness reuse** between ElGamal ciphertexts and payload encryption keys. This allowed an attacker to perform trial decryption, potentially revealing sender, receiver, and amount for transactions made with vulnerable wallet software. **Key points:** - **Fixed in Release142** via `ENCRYPTED_DEFAULT_PAYLOAD_CBOR_V2` - **Affected:** Wallet-layer privacy (sender/receiver/amount deanonymization) - **Not affected:** Consensus layer, ledger integrity, transaction validity - **Historical transactions** made before Release142 remain potentially affected **Recommendation:** Use Release142+ wallets for hardened payload encryption. --- ## Related Pages **Security Suite:** - [Transaction Proofs](/integrity/transaction-proofs.md) - The six sigma system - [Ring Member Behavior](/integrity/ring-member-behavior.md) - Why sender can't be identified **Privacy Suite:** - [Ring Signatures](/privacy/ring-signatures.md) - Sender anonymity - [Payload Proofs](/privacy/payload-proofs.md) - Complete payload proof explanation --- --- title: "Proof Verification Flow: End-to-End Transaction Validation | DERO Blockchain" description: "Complete walkthrough of how DERO validates transactions from creation through network acceptance - every step of the cryptographic verification process." keywords: ["proof verification", "transaction validation", "DERO verification", "cryptographic verification", "consensus validation", "transaction flow"] date: "2025-01-20" lastUpdated: "2026-02-06" authors: ["DHEBP"] slug: "proof-verification-flow" canonicalUrl: "https://derod.org/integrity/proof-verification-flow" tags: ["security", "verification", "transactions", "technical", "flow"] --- # Proof Verification Flow **End-to-End Security:** Every transaction goes through a complete verification pipeline - from wallet creation through network validation to blockchain acceptance. This page traces the entire journey. ## The Complete Flow ```mermaid sequenceDiagram participant W as Wallet participant N as Network Node participant V as Verifier participant BC as Blockchain Note over W: Phase 1: Creation W->>W: Generate proofs W->>W: Sign transaction Note over N: Phase 2: Broadcast W->>N: Submit TX (TLS encrypted) N->>N: Basic format check Note over V: Phase 3: Verification N->>V: Full verification V->>V: Verify all 6 sigma proofs (A_y, A_D, A_b, A_X, A_t, A_u) V->>V: Verify inner product proof (closes the A_t bulletproof) Note over BC: Phase 4: Acceptance V-->>N: Valid/Invalid alt All proofs valid N->>BC: Add to mempool BC->>BC: Include in block BC->>BC: Update state else Any proof invalid N-->>W: Reject transaction end ``` --- ## Phase 1: Transaction Creation (Wallet) ### Step 1.1: Prepare Transaction Data **What happens in the wallet** (see `walletapi/wallet_transfer.go`): 1. **Check balance** -- Retrieve the sender's current encrypted balance from the daemon 2. **Select ring members** -- Request random addresses from the daemon to form the ring (decoys) 3. **Create transfer commitment** -- Encrypt the transfer amount using the recipient's public key 4. **Proceed to proof generation** -- Build the cryptographic proofs for the transaction ### Step 1.2: Generate Proofs **The proof generation sequence:** ```mermaid flowchart TD A["Transaction Data"] --> B["Generate Commitments"] B --> C["Generate A_y (secret key)"] C --> D["Generate A_D (balance update)"] D --> E["Generate A_b (balance commitment)"] E --> F["Generate A_X (constraints)"] F --> G["Generate A_t (range proof)"] G --> H["Generate A_u (key image)"] H --> I["Compute Challenge Hash"] I --> J["Generate Responses (s_y, s_D, ...)"] J --> K["Generate Inner Product Proof"] K --> L["Assemble Complete Transaction"] ``` **Source:** `cryptography/crypto/proof_generate.go` The proof generation function builds all components in sequence: 1. **Create commitments** for each sigma proof component (A_y, A_D, A_b, A_X, A_t, A_u) 2. **Packing + bit decomposition** during the bulletproof input setup: the packing step `number := btransfer.Add(btransfer, bdiff.Lsh(bdiff, 64))` is at `proof_generate.go:468-471`; the bit-decomposition loop (`number_string` reversal + `aL` / `aR` `for`-loop) is at `proof_generate.go:473-487`. Together they encode the packed 128-bit value as the bit vectors the bulletproof commits to. 3. **Compute challenge hash** binding all six components together via `reducedhash()` 4. **Generate responses** (s_y, s_D, etc.) using the challenge `c` and secret values 5. **Generate inner product proof** for the bulletproof range verification ### Step 1.3: Where the actual safeguard lives The wallet's bit decomposition above is **proof construction**, not protection. A malicious sender controls their own wallet and could patch any client-side check. The cryptographic guarantee for non-negative amounts comes from the **verifier's** bulletproof check that every node runs in Phase 3 โ€” by bulletproof soundness, no prover can construct a verifying proof for an out-of-range committed value. **[Full derivation โ†’](/integrity/negative-transfer-protection.md)** --- ## Phase 2: Network Broadcast ### Step 2.1: TLS Encryption ```mermaid flowchart TD W["Wallet"] -->|"TLS Encrypted"| N["Network"] subgraph "What ISP Sees" E["Encrypted blob
Cannot read content"] end ``` **From Source Code** (`p2p/controller.go`): ```go // Outgoing connections use TLS conntls := tls.Client(conn, &tls.Config{InsecureSkipVerify: true}) ``` ### Step 2.2: Basic Format Check **Before full verification, nodes do quick sanity checks:** - Transaction size is within acceptable limits - Required proof fields are present and properly formatted - Basic structural validity (correct number of payloads, ring sizes within `MIN_RINGSIZE`/`MAX_RINGSIZE` from `config/config.go`) If format checks fail, the transaction is rejected immediately without proceeding to expensive cryptographic verification. --- ## Phase 3: Full Verification **Five Highlighted Checkpoints:** The verification process includes many checks. Below are five key checkpoints that must pass. Failure at any checkpoint results in immediate rejection. ### The Five Verification Checkpoints ```mermaid flowchart TD TX["Transaction Submitted"] --> C1{"Checkpoint 1:
Overflow Check"} C1 -->|Fail| REJ["โŒ REJECTED"] C1 -->|Pass| C2{"Checkpoint 2:
Parity Check"} C2 -->|Fail| REJ C2 -->|Pass| C3{"Checkpoint 3:
B^w ร— A Recovery"} C3 -->|Fail| REJ C3 -->|Pass| C4{"Checkpoint 4:
Challenge Hash (c)"} C4 -->|Fail| REJ C4 -->|Pass| C5{"Checkpoint 5:
Inner Product"} C5 -->|Fail| REJ C5 -->|Pass| ACC["โœ… ACCEPTED"] ``` --- ### Checkpoint 1: Overflow Protection **Location:** `proof_verify.go:108-111` ```go // Prevent integer overflow attacks on fees total_open_value := s.Fees + extra_value if total_open_value < s.Fees || total_open_value < extra_value { return false // Overflow detected! } ``` **What it catches:** Arithmetic overflow attacks that could manipulate transaction fees. **[Learn more โ†’](/integrity/overflow-protection.md)** --- ### Checkpoint 2: Parity Check **Location:** `proof_verify.go:136-141` ```go // Verify the secret parity is well-formed if anonsupport.w.Cmp(proof.f.vector[0]) == 0 || anonsupport.w.Cmp(proof.f.vector[m]) == 0 { // Parity is well formed - continue } else { Logger.V(1).Info("Parity check failed") return false } ``` **What it catches:** Invalid sender index encoding. The parity check ensures the prover knows which ring member position they occupy without revealing it. **Why it matters:** In a ring signature, the real sender's position is hidden among decoys. The parity check cryptographically verifies the prover knows their position without revealing which one it is. This check is the verification-side counterpart of the parity constraint enforced at transaction build time โ€” sender and receiver must occupy indices of different parity (one even, one odd), splitting the ring evenly between potential senders and potential recipients. See [The Parity Constraint](/privacy/ring-signatures.md#the-parity-constraint-how-the-ring-is-split) for the full structural explanation. --- ### Checkpoint 3: B^w ร— A Recovery **Location:** `proof_verify.go:162-179` ```go // proof_verify.go:161-179 (actual source) // check whether we successfuly recover B^w * A stored := new(bn256.G1).Add(new(bn256.G1).ScalarMult(proof.B, anonsupport.w), proof.A) computed := new(bn256.G1).Add(anonsupport.temp, new(bn256.G1).ScalarMult(gparams.H, proof.z_A)) // ... debug logging (lines 165-175) ... if stored.String() != computed.String() { // line 177 Logger.V(1).Info("Recover key failed B^w * A") return false } ``` **What it catches:** Malformed proof structure. This verifies the polynomial commitment structure is consistent. --- ### Checkpoint 4: Challenge Hash Verification **Location:** `proof_verify.go:410-425` ```go // Recompute challenge hash and verify it matches var input []byte input = append(input, ConvertBigIntToByte(x)...) input = append(input, sigmasupport.A_y.Marshal()...) input = append(input, sigmasupport.A_D.Marshal()...) input = append(input, sigmasupport.A_b.Marshal()...) input = append(input, sigmasupport.A_X.Marshal()...) input = append(input, sigmasupport.A_t.Marshal()...) input = append(input, sigmasupport.A_u.Marshal()...) if reducedhash(input).Text(16) != proof.c.Text(16) { Logger.V(1).Info("C calculation failed") return false } ``` **What it catches:** Any tampering with proof components. If ANY proof element was modified, the challenge hash won't match. --- ### Checkpoint 5: Inner Product Verification **Location:** `proof_verify.go:457-459` ```go // Final cryptographic verification if !proof.ip.Verify(hPrimes, u_x, P, o, gparams) { Logger.V(1).Info("inner proof failed") return false } ``` **What it catches:** Invalid range proofs, forged bit commitments, and any cryptographic inconsistency in the bulletproof. --- ### Step 3.1: Recompute Challenge Hash **The verifier recomputes the challenge from the submitted proofs.** From `proof_verify.go:410-425`, the verifier builds an input byte array from all six recovered sigma components (A_y, A_D, A_b, A_X, A_t, A_u), then runs `reducedhash()` over them. The result must match the `proof.c` value submitted with the transaction: ```go // proof_verify.go:410-425 (actual source) var input []byte input = append(input, ConvertBigIntToByte(x)...) input = append(input, sigmasupport.A_y.Marshal()...) input = append(input, sigmasupport.A_D.Marshal()...) input = append(input, sigmasupport.A_b.Marshal()...) input = append(input, sigmasupport.A_X.Marshal()...) input = append(input, sigmasupport.A_t.Marshal()...) input = append(input, sigmasupport.A_u.Marshal()...) if reducedhash(input).Text(16) != proof.c.Text(16) { Logger.V(1).Info("C calculation failed") return false } ``` If any proof component was tampered with, the recomputed hash won't match `proof.c`, and verification fails. ### Step 3.2: Verify Each Proof ### A_y: Secret Key **A_y: Secret Key Proof** Uses Schnorr-style verification: checks that the response `s_y` is consistent with the commitment `A_y`, the challenge `c`, and the sender's public key. This proves the sender possesses the private key without revealing it. **What it proves:** Sender owns the funds ### A_D: Balance Update **A_D: Balance Update Proof** Verifies that the encrypted balance update is mathematically correct using homomorphic properties: `E(old_balance) - E(amount) = E(new_balance)`. The verification checks this relationship holds without decrypting any values. **What it proves:** Balance math is correct (old - amount = new) ### A_t: Range Proof **A_t: Range Proof** The bulletproof range proof component. Commits the combined 128-bit value (transfer amount in lower 64 bits + remaining balance in upper 64 bits) as a bit decomposition, along with the structural commitments the verifier needs. The actual range check is closed by the inner product proof (next tab) โ€” by bulletproof soundness, that closure rejects any committed value outside the proven range. **What it proves:** Amount is valid (not negative, not overflow) **[Full technical details โ†’](/integrity/range-proof-integrity.md)** ### Inner Product **Inner Product Proof (closes A_t)** The recursive closure of the A_t bulletproof. From `proof_verify.go:457-459`: ```go if !proof.ip.Verify(hPrimes, u_x, P, o, gparams) { Logger.V(1).Info("inner proof failed") return false } ``` This is the bulletproof sub-protocol that completes A_t's range check. Uses 7 rounds of halving (from `proof_innerproduct.go:71: length := 7`) to verify the 128-bit range constraint. The IP argument and A_t are not independent checks โ€” passing the IP is what makes A_t valid. **What it proves:** A_t's range constraint holds (by bulletproof soundness, no out-of-range value can produce a passing IP proof) ### Step 3.3: All-or-Nothing Decision ```mermaid flowchart TD V["Verification Start"] --> A{"A_y valid?"} A -->|No| REJ["โŒ REJECT"] A -->|Yes| B{"A_D valid?"} B -->|No| REJ B -->|Yes| C{"A_b valid?"} C -->|No| REJ C -->|Yes| D{"A_X valid?"} D -->|No| REJ D -->|Yes| F{"A_u valid?"} F -->|No| REJ F -->|Yes| E{"A_t valid?
(closed by inner product proof)"} E -->|No| REJ E -->|Yes| ACC["โœ… ACCEPT"] ``` **Key Point:** ALL proofs must pass. There is no "partial acceptance." --- ## Phase 4: Blockchain Acceptance ### Step 4.1: Mempool Addition Before a transaction enters the mempool, the node: 1. **Full verification** -- Runs the complete `Verify()` function from `proof_verify.go:98` (all checkpoints must pass) 2. **Duplicate check** -- Ensures the transaction isn't already in the mempool 3. **State check** -- Confirms the transaction is valid against current chain state 4. **Add to mempool** -- Transaction is queued for inclusion in a future block ### Step 4.2: Block Inclusion ```mermaid sequenceDiagram participant MP as Mempool participant M as Miner participant BC as Blockchain participant N as Network MP->>M: Select transactions M->>M: Create block candidate M->>M: Mine block (AstroBWT) M->>BC: Submit block BC->>BC: Verify block + all TXs BC->>N: Propagate valid block N->>N: All nodes verify & accept ``` ### Step 4.3: State Update Once a transaction is included in a block, the state is updated (see `blockchain/transaction_execute.go`): 1. **Update encrypted balances** -- For each ring member, the encrypted balance is updated using `ElGamal.Add()` from `cryptography/crypto/algebra_elgamal.go:69`. All ring members' encrypted balances change (see [Ring Member Behavior](/integrity/ring-member-behavior.md)), but only the real sender/receiver's decrypted balance changes. 2. **Record the transaction** -- The transaction is committed to the chain state via Graviton (DERO's key-value store). --- ## Security at Each Phase | Phase | What's Checked | Attack Prevented | |-------|---------------|------------------| | **Creation** | Proof construction (wallet-side) | None on its own โ€” an attacker controls their wallet | | **Broadcast** | TLS encryption | Network snooping | | **Verification** | All proofs (incl. bulletproof soundness) | Forgery, transaction replay, negative/out-of-range amounts | | **Acceptance** | Consensus | Byzantine actors | --- ## Verification Order | Step | What Happens | |------|-------------| | **Format check** | Basic structural validation (field counts, size limits, parity) | | **Proof verification** | All six sigma proofs recovered and challenge hash recomputed | | **Inner product** | Recursive 7-round inner product proof verified (bulletproof sub-component of A_t) | | **Consensus** | Transaction included in next block (~18s block time from `config/config.go:34`) | > **Note:** No official benchmarks exist for per-step verification times. The codebase does not include benchmark tests. Actual performance depends on hardware and ring size. --- ## Key Takeaways ### The Verification Guarantee ``` Transaction Accepted โŸบ ALL of: โœ“ Wallet could generate valid proofs โœ“ TLS encrypted during transit โœ“ All 6 sigma proofs valid (A_y, A_D, A_b, A_X, A_t, A_u) โœ“ Inner product proof valid (the recursive closure that completes A_t's bulletproof) โœ“ Nonce/height valid (replay prevention) โœ“ Consensus acceptance ``` ### Why Invalid Transactions Cannot Succeed **Verifier-enforced, then consensus-confirmed:** Invalid transactions are rejected by the verifier itself, regardless of what the sender's wallet does. Every node independently re-runs the proof system; by bulletproof soundness, no out-of-range or negative committed value can produce a passing proof. Consensus then ensures all honest nodes agree on the outcome. --- ## Related Pages **Security Suite:** - [Transaction Proofs](/integrity/transaction-proofs.md) - The six sigma system - [Range Proof Integrity](/integrity/range-proof-integrity.md) - 128-bit range proof closed at the verifier - [Network Consensus](/integrity/network-consensus-validation.md) - Distributed validation **Technical Reference:** - [Daemon RPC API](/rpc-api/daemon-rpc-api.md) - Transaction submission - [Wallet RPC API](/rpc-api/wallet-rpc-api.md) - Transaction creation --- --- title: "Range Proof Integrity: How DERO's Bulletproof Binds Amounts | DERO Blockchain" description: "Every DERO transfer carries a 128-bit Bulletproof range proof that binds the transfer amount and remaining balance to non-negative 64-bit ranges. Enforced independently by every node โ€” out-of-range values cannot produce a verifying proof." keywords: ["range proofs", "bulletproofs", "DERO security", "amount validation", "cryptographic proofs", "inner product proof", "bulletproof soundness"] date: "2025-01-20" lastUpdated: "2026-05-26" authors: ["DHEBP"] slug: "range-proof-integrity" canonicalUrl: "https://derod.org/integrity/range-proof-integrity" tags: ["security", "range-proofs", "bulletproofs", "cryptography", "technical"] --- # Range Proof Integrity **What the range proof binds:** Every DERO transfer carries a Bulletproof range proof. One proof binds **two** quantities โ€” the transfer amount and the sender's remaining balance โ€” to non-negative 64-bit ranges. Every node verifies the proof independently. By the soundness of Bulletproofs, an out-of-range value cannot produce a proof that verifies. ## What the range proof proves DERO packs **two** quantities into a single 128-bit value and range-proves them together. The packing step is at `cryptography/crypto/proof_generate.go:468-471` and the bit-decomposition loop that feeds the bulletproof is at `proof_generate.go:473-487`: ```go btransfer := new(big.Int).SetInt64(int64(witness.TransferAmount)) // this should be reduced bdiff := new(big.Int).SetInt64(int64(witness.Balance)) // this should be reduced number := btransfer.Add(btransfer, bdiff.Lsh(bdiff, 64)) // 128-bit value to range-prove ``` The trailing `// this should be reduced` comments are the DERO author's own forensic note in source โ€” flagging that reduction modulo the bn256 group order should be applied to these inputs. They are preserved verbatim here because they carry that authorial signal. So one Bulletproof establishes **both**: - the **transfer amount** is a valid non-negative 64-bit number (low 64 bits), and - the sender's **remaining balance** is a valid non-negative 64-bit number (high 64 bits). **Why both matter:** proving only the amount is non-negative would not stop an overspend. By also proving the remaining balance is non-negative, the same proof guarantees you cannot send more than you hold โ€” and cannot manufacture a balance by sending a "negative" amount. --- ## The cryptographic guarantee By the **computational soundness** of Bulletproofs โ€” under the discrete-log assumption on the bn256 curve, in the random oracle model (Fiat-Shamir) โ€” no prover can construct a proof that *verifies* for a committed value outside the proven range, except with negligible probability bounded by the underlying hardness. Combined with DERO's homomorphic accounting (inputs and outputs bound to balance exactly), value cannot be created from nothing. See [Cryptographic Assumptions](/integrity/transaction-proofs.md#cryptographic-assumptions) for the full assumption stack. A "negative" transfer is the `uint64` wraparound of a value near `2^64`. It fails the range proof from both directions: | Attack framing | Why the range proof rejects it | |---|---| | Treat the wraparound as the **transfer amount** | A value near `2^64` lies outside `[0, 2^64)` โ€” the low-64 range bound fails. | | Treat it as **receiving** (so your own balance jumps) | The conservation proof forces a matching decrease; the sender's **remaining balance** goes negative โ†’ wraps โ†’ the high-64 range bound fails. | There is no "almost in range," no rounding, no edge case: either a verifying proof exists (value in range) or it does not. Full soundness derivation and the canonical refutation of the "minus sign breaks the bit loop" misconception: [Negative Transfer Protection](/integrity/negative-transfer-protection.md). --- ## Where the guarantee actually lives The protection lives in **verification**, not generation. The wallet builds the proof in `proof_generate.go`; an attacker controls their own wallet and could patch out any client-side check. The cryptographic guarantee comes from `proof_verify.go`, which every node runs independently before accepting a block. | Layer | What runs | Who controls it | Is this the safeguard? | |---|---|---|---| | Wallet proof generation | `proof_generate.go` | Sender (attacker if malicious) | No โ€” can be patched by the attacker | | Node proof verification | `proof_verify.go` | Every validating node | **Yes** โ€” soundness ensures rejection of out-of-range proofs | A common misconception holds that Go's `BigInt.Text(2)` emitting a `'-'` for negative values "breaks the bit loop" in proof generation, and that this is what stops negative transfers. It does not. The loop is `if b == '1' { โ€ฆ } else { โ€ฆ }` โ€” a stray `'-'` byte is silently treated as a `0` bit, not rejected. And for any real transaction, the packed 128-bit `number` is positive, so `Text(2)` produces no `'-'` at all. See [Negative Transfer Protection](/integrity/negative-transfer-protection.md) for the full teardown. --- ## How the Bulletproof verification works The Bulletproof proves the 128-bit committed value is in range by decomposing it into 128 bits, committing to two vectors derived from those bits, and proving in zero knowledge that each component is a single bit and that the bits reconstruct the committed value. The verification reduces this to a single inner-product check using a recursive halving algorithm โ€” what makes the proof logarithmic in size. ### The recursive inner product ```mermaid flowchart TD A["Start: 128 bits"] --> B["Split: 64 + 64"] B --> C["Commit: Lโ‚, Rโ‚"] C --> D["Challenge: xโ‚"] D --> E["Fold: 64 bits"] E --> F["Split: 32 + 32"] F --> G["Commit: Lโ‚‚, Rโ‚‚"] G --> H["Challenge: xโ‚‚"] H --> I["Fold: 32 bits"] I --> J["โ€ฆ continue โ€ฆ"] J --> K["Final: 1 element"] K --> L["Verify: final equals committed"] ``` **At each step:** - Create commitments L and R - Derive challenge from hash - Fold vectors in half - Repeat until a single element remains (`logโ‚‚(128) = 7` rounds, `cryptography/crypto/proof_innerproduct.go`) If the final inner product does not match the committed value, the check at `proof_verify.go:457-460` fails โ€” and the transaction is rejected at consensus. --- ## Verify it yourself ```bash git clone https://github.com/deroproject/derohe.git cd derohe # The 128-bit packing (proof generation) sed -n '466,490p' cryptography/crypto/proof_generate.go # The verification every node runs (the actual enforcement) sed -n '457,460p' cryptography/crypto/proof_verify.go # The recursive inner product algorithm grep -n "length" cryptography/crypto/proof_innerproduct.go ``` For the soundness argument and the proof that out-of-range values cannot produce a verifying proof, see [Negative Transfer Protection](/integrity/negative-transfer-protection.md). --- ## Related Pages **Security suite:** - [Negative Transfer Protection](/integrity/negative-transfer-protection.md) โ€” soundness derivation, misconception teardown - [Transaction Proofs](/integrity/transaction-proofs.md) โ€” the full proof set every node checks - [Proof Verification Flow](/integrity/proof-verification-flow.md) โ€” end-to-end validation - [Inflation Claim](/integrity/inflation-claim.md) โ€” what the 2022 case actually shows **Privacy suite:** - [Bulletproofs](/privacy/bulletproofs.md) โ€” zero-knowledge range proofs --- --- title: "Ring Member Behavior: Understanding Decoy Participation | DERO Blockchain" description: "Technical explanation of why ring members' encrypted balances change even as decoys - this is normal behavior by design, not a protocol anomaly." keywords: ["ring member", "decoy", "ring signature", "balance change", "DERO privacy", "plausible deniability", "ring decoy"] date: "2025-01-20" lastUpdated: "2026-02-06" authors: ["DHEBP"] slug: "ring-member-behavior" canonicalUrl: "https://derod.org/integrity/ring-member-behavior" tags: ["security", "ring-signatures", "privacy", "decoys", "technical"] --- # Ring Member Behavior **Critical Understanding:** Encrypted balance changes occur for ALL ring members in a transaction, including decoys. This is **by design** - it's how ring signatures provide plausible deniability. Observing a balance change does NOT mean an address was the sender. **Naming note:** "Ring signature" is the user-facing name DERO uses for what the source actually implements as an Anonymous Zether-style anonymity-set ZK proof (see `cryptography/crypto/proof_generate.go` and `proof_verify.go`). The user-facing term is colloquial; the construction is not a classical (Schnorr/LSAG/MLSAG) ring signature. ## The Core Mechanism ### How Ring Signatures Work When Alice sends DERO to Bob: ```mermaid flowchart TD A["Alice wants to send 100 DERO"] --> B["Wallet selects ring members"] B --> C["Ring: Alice + 15 decoys"] subgraph "Ring Members" M1["Member 0: Decoy"] M2["Member 1: Decoy"] M7["Member 7: ALICE (real)"] M15["Member 15: Decoy"] end C --> D["Create ring signature"] D --> E["ALL 16 encrypted balances
participate in operation"] E --> F["Blockchain sees:
ONE of 8 possible senders sent it"] F --> G["Cannot determine which"] ``` ### Why Decoy Balances Change **From Source Code** (`walletapi/daemon_communication.go:863-903`): ```go // When processing a transaction, check if our address is a ring member if bytes.Compare(compressed_address, tx.Payloads[t].Statement.Publickeylist_compressed[j][:]) == 0 { // Our address is in this ring! // Lines 886-889: Encrypted balance changes for ALL ring members changes := crypto.ConstructElGamal(tx.Payloads[t].Statement.C[j], tx.Payloads[t].Statement.D) changed_balance_e := previous_balance_e_tx.Add(changes) previous_balance_e_tx = new(crypto.ElGamal).Deserialize(changed_balance_e.Serialize()) // Lines 900-903: Identify if we were just a decoy switch { case previous_balance == changed_balance: ring_member = true // We were a decoy - balance unchanged after decryption } } ``` **Key Insight:** The encrypted balance data changes for ALL ring members, but only the real sender's *decrypted* balance actually changes. --- ## The Two Types of Balance Changes ### Encrypted vs. Decrypted ### Encrypted Balance **Encrypted Balance (66 bytes)** ``` What network sees: Ring member (decoy): Before: "002a319487393969e9552e..." After: "a58442215349d55ceaac04..." โ† DIFFERENT! Real sender: Before: "7f8e2a1b3c4d5e6f7a8b..." After: "1a2b3c4d5e6f7a8b9c0d..." โ† DIFFERENT! Both encrypted balances change! Cannot distinguish sender from decoy! ``` ### Decrypted Balance **Decrypted Balance (Only Owner Sees)** ``` What owner sees (with private key): Ring member (decoy): Before: 500 DERO After: 500 DERO โ† SAME! Real sender: Before: 500 DERO After: 400 DERO โ† DIFFERENT! Only real sender's balance changes! But only they can see this! ``` --- ## Why This Design? ### The Privacy Guarantee ```mermaid flowchart TD subgraph "Without Balance Change" A1["Attacker sees:
15 balances unchanged
1 balance changed"] A1 --> B1["Attacker knows:
Changed one = sender"] B1 --> C1["Privacy: โŒ BROKEN"] end subgraph "With Balance Change (DERO)" A2["Attacker sees:
16 balances changed
(encrypted)"] A2 --> B2["Attacker knows:
One of 8 possible senders is the real sender"] B2 --> C2["Privacy: โœ… PRESERVED"] end ``` **The key insight:** If only the real sender's encrypted balance changed, an observer could identify them immediately. By having all ring members' encrypted balances change, the sender remains hidden. ### Plausible Deniability **Legal Protection:** If accused of sending a transaction, you can truthfully say: "My encrypted balance changed, but that only means I was in the ring. Any of the 8 potential senders in this ring could be the real sender." This is cryptographically provable. --- ## What Balance Changes Mean ### Interpretation Guide | Observation | What It Means | What It Doesn't Mean | |-------------|--------------|---------------------| | **Encrypted balance unchanged** | Address not in ANY ring | - | | **Encrypted balance changed** | Address was in a ring | โ‰  Address was sender | | **Multiple changes over time** | Address in multiple rings | โ‰  Address sent multiple times | | **Decrypted balance unchanged** | Was decoy (owner can verify) | Only owner knows this | | **Decrypted balance changed** | Was real sender (owner can verify) | Only owner knows this | ### The Unchanged Balance Test **If encrypted balance is unchanged for X blocks:** ``` Unchanged encrypted balance = NOT involved in ANY transaction This means: โœ— Not a sender โœ— Not a receiver โœ— Not a decoy โœ— Not a ring member at all The address has zero blockchain activity for that period. ``` **This is powerful evidence** - unchanged encrypted balance definitively proves no involvement. --- ## Ring Member Selection ### How Decoys Are Chosen **Source** (`cmd/derod/rpc/rpc_dero_getrandomaddress.go:80-111` โ€” quoted verbatim): ```go account_map := map[string]bool{} for i := 0; i < 100; i++ { k, v, err := balance_tree.Random() if err != nil { continue } v_old, err := balance_tree_old.Get(k) if err != nil { continue } if bytes.Compare(v, v_old) != 0 { continue // docs: balance recently changed โ†’ not a stable decoy } var acckey crypto.Point if err := acckey.DecodeCompressed(k[:]); err != nil { continue } addr := rpc.NewAddressFromKeys(&acckey) addr.Mainnet = (globals.Config.Name == config.Mainnet.Name) account_map[addr.String()] = true if len(account_map) > 140 { break } } // docs: returns up to ~140 candidate addresses; wallet samples ring_size-1 of them. ``` ### Selection Criteria | Requirement | Reason | |-------------|--------| | **Unchanged balance (5 blocks)** | Better decoys | | **Random selection** | Prevents targeting | | **Multiple candidates** | Ensures diversity | --- ## Example: Tracing a Transaction ### The Scenario ``` Transaction at block 1,081,893: Ring size: 16 members (8 sender slots, 8 recipient slots) One of the 8 possible senders sent 100 DERO ``` ### What an Observer Sees ``` Address 0: Encrypted balance changed Address 1: Encrypted balance changed Address 2: Encrypted balance changed ... Address 7: Encrypted balance changed โ† Could be sender ... Address 15: Encrypted balance changed ALL 16 encrypted balances changed. Which of the 8 possible senders is the real sender? UNKNOWN. ``` ### What Each Owner Sees ``` Address 0 owner: "My decrypted balance is same. I was a decoy." Address 1 owner: "My decrypted balance is same. I was a decoy." ... Address 7 owner: "My decrypted balance is 100 less. I was the sender." ... Address 15 owner: "My decrypted balance is same. I was a decoy." Only Address 7's owner knows they sent. Nobody else can prove it. ``` --- ## Sender vs. Decoy: How to Verify ### Method 1: Decrypt Balance (Owner Only) The wallet performs this check automatically. From `walletapi/daemon_communication.go:900-903`: ```go switch { case previous_balance == changed_balance: ring_member = true // We were a decoy - balance unchanged after decryption case previous_balance > changed_balance: // We were the sender - balance decreased ``` The wallet decrypts the balance before and after the transaction using the owner's private key. If the decrypted balance is unchanged, you were a decoy. If it decreased, you were the sender. ### Method 2: Check Wallet History (Owner Only) ```bash # Wallet shows transaction history dero-wallet-cli > balance > show_transfers ``` ### Method 3: External Observation (IMPOSSIBLE) ``` Observer can see: โœ“ Encrypted balance changed โœ— Decrypted balance โœ— Who the sender is โœ— Proof that any specific address sent Conclusion: Cannot determine sender from outside ``` --- ## Common Misconceptions ### Misconception 1: "Balance change = sent transaction" **Reality:** Balance change only means the address was in a ring. Could be sender OR decoy. ### Misconception 2: "Can track senders by balance changes" **Reality:** All ring members' balances change. Tracking balance changes tracks ring membership, not sending. ### Misconception 3: "Unchanged balance = received" **Reality:** Unchanged encrypted balance = no involvement at all (not sending, not receiving, not in any ring). ### Misconception 4: "Third parties can verify sender" **Reality:** Only the owner (with private key) can determine if they were sender or decoy. This is privacy by design. --- ## Security Implications ### What This Protects | Threat | How Ring Member Behavior Helps | |--------|-------------------------------| | **Sender identification** | All ring members look the same | | **Transaction linking** | Each TX has independent ring | | **Balance analysis** | Encrypted balances hide amounts | | **Statistical attacks** | Random decoy selection | ### The Privacy Guarantee **Mathematical Privacy:** The probability of correctly identifying the sender is exactly 1/(ring_size/2) (e.g., 12.5% for ring size 16). Rings are split evenly โ€” half are potential senders, half are potential recipients โ€” so the anonymity set for the sender is ring_size/2. This is not "hard to guess" - it's mathematically guaranteed randomness. **Source:** This split is enforced by a parity constraint in `walletapi/transaction_build.go:79-90` and by the P/Q polynomial structure in `cryptography/crypto/proof_generate.go:700-710`. See [The Parity Constraint](/privacy/ring-signatures.md#the-parity-constraint-how-the-ring-is-split) for the full source-code-verified breakdown. --- ## Key Takeaways ### The Design Principle ``` Ring signature privacy requires: 1. Multiple addresses in ring 2. All encrypted balances participate equally 3. No observable difference between sender and decoys 4. Only owner can decrypt their balance Result: Perfect plausible deniability ``` ### For Users - **Your encrypted balance will change** when you're selected as a decoy - This is **normal** and **expected** - It does **not** mean you sent anything - Only **you** know if you were sender or decoy - This **protects your privacy** when you ARE the sender ### For Analysts - **Encrypted balance changes** indicate ring membership only - **Cannot determine** sender vs. decoy from encrypted data - **Statistical analysis** faces 1/(ring_size/2) probability barrier (e.g., 1/8 for ring size 16) - **Definitively proving** sender identity is cryptographically impossible --- ## Related Pages **Security Suite:** - [Balance Mechanics](/integrity/balance-mechanics.md) - Encrypted balance structure - [Proof Types Explained](/integrity/payload-vs-transaction-proofs.md) - Why third parties can't verify **Privacy Suite:** - [Ring Signatures](/privacy/ring-signatures.md) - Complete ring signature explanation - [Transaction Privacy](/privacy/transaction-privacy.md) - Full privacy model --- --- title: "Transaction Proofs: DERO's Six Sigma Proof System | DERO Blockchain" description: "Technical deep dive into DERO's six interconnected transaction proofs - how they work together to guarantee transaction integrity through cryptographic binding." keywords: ["transaction proofs", "sigma proofs", "DERO proofs", "cryptographic proofs", "proof verification", "A_y proof", "A_D proof", "challenge hash"] date: "2025-01-20" lastUpdated: "2026-02-06" authors: ["DHEBP"] slug: "transaction-proofs" canonicalUrl: "https://derod.org/integrity/transaction-proofs" tags: ["security", "proofs", "cryptography", "technical"] --- # Transaction Proofs: The Six Sigma System **Core Principle:** Six interconnected proofs bound by a cryptographic hash. If you fake one proof, the hash changes, which invalidates all other proofs. This creates an all-or-nothing security model. ## What Problem Do Transaction Proofs Solve? **The Challenge:** ``` DERO needs to verify: โœ“ Sender owns the funds (has private key) โœ“ Balance update is mathematically correct โœ“ Amount is valid (not negative, not impossible) โœ“ Transaction is bound to sender's secret key (key image) โœ“ All protocol constraints satisfied But WITHOUT revealing: โœ— The sender's identity โœ— The actual amounts โœ— The balances ``` **The Solution: Six Sigma Proofs** - โœ… Each proof validates one aspect - โœ… All proofs bound together cryptographically - โœ… All-or-nothing cryptographic binding โ€” faking one breaks all - โœ… Zero-knowledge (reveals nothing) --- ## The Six Proofs ```mermaid flowchart TD subgraph "Transaction Proofs" A_y["A_y
Secret Key Proof"] A_D["A_D
Balance Update"] A_b["A_b
Balance Commitment"] A_X["A_X
Constraints"] A_t["A_t
Range Proof"] A_u["A_u
Key Image"] end A_y --> H["Challenge Hash (c)
= hash(A_y || A_D || A_b || A_X || A_t || A_u || ...)"] A_D --> H A_b --> H A_X --> H A_t --> H A_u --> H H --> V{"Verify All
Against c"} V -->|All Pass| ACC["Transaction Accepted"] V -->|Any Fail| REJ["Transaction Rejected"] ``` ### Proof Details | Proof | What It Validates | Why It's Needed | |-------|------------------|-----------------| | **A_y** | Sender possesses private key | Prevents unauthorized spending | | **A_D** | Encrypted balance update is correct | Ensures math is right | | **A_b** | Balance commitment is valid | Binding and hiding properties | | **A_X** | Additional protocol constraints | Protocol-specific rules | | **A_t** | Combined 128-bit value with 64-bit bounds | Prevents negative/overflow | | **A_u** | Key image (linking tag) is correctly derived | Binds transaction to sender's secret key | --- ## How They're Bound Together ### The Challenge Hash **From Source Code** (`cryptography/crypto/proof_verify.go:410-425`): ```go // All six sigma proof components contribute to the challenge hash var input []byte input = append(input, ConvertBigIntToByte(x)...) input = append(input, sigmasupport.A_y.Marshal()...) input = append(input, sigmasupport.A_D.Marshal()...) input = append(input, sigmasupport.A_b.Marshal()...) input = append(input, sigmasupport.A_X.Marshal()...) input = append(input, sigmasupport.A_t.Marshal()...) input = append(input, sigmasupport.A_u.Marshal()...) // Challenge 'c' must match - if any component was tampered, this fails if reducedhash(input).Text(16) != proof.c.Text(16) { Logger.V(1).Info("C calculation failed") return false } ``` **The Binding Effect:** ```mermaid flowchart TD subgraph "Proof Generation" P1["Generate A_y"] --> H1["Add to hash"] P2["Generate A_D"] --> H1 P3["Generate A_b"] --> H1 P4["Generate A_X"] --> H1 P5["Generate A_t"] --> H1 P6["Generate A_u"] --> H1 H1 --> C["Challenge c"] end subgraph "Response Generation" C --> R1["s_y = k_y + cร—x_y"] C --> R2["s_D = k_D + cร—x_D"] C --> R3["s_b = k_b + cร—x_b"] end ``` ### Why This Prevents Forgery ### The Attack **Attacker's Goal:** ``` Attacker wants to: 1. Fake A_t (range proof) to allow negative amount 2. Keep other proofs valid Strategy: 1. Create fake A_t' (allows -1000 DERO) 2. Submit with real A_y, A_D, A_b, A_X, A_u ``` ### Why It Fails **Why It Fails:** ``` 1. Fake A_t' is different from real A_t 2. Challenge hash changes: c' = hash(A_y || A_D || A_b || A_X || A_t' || A_u) c' โ‰  c (original) 3. All responses were computed with c, not c': s_y = k_y + cร—x_y (computed with c) 4. Verification uses c' but responses use c: verify(A_y, s_y, c') โ†’ FAILS 5. ALL proofs fail verification, not just A_t ``` **Key Insight:** The challenge hash creates a **circular dependency**. You need all proofs to compute the hash, but you need the hash to create valid responses. Changing any proof changes the hash, which invalidates all responses. --- ## Each Proof Explained ### A_y: Secret Key Proof **Purpose:** Proves sender possesses the private key without revealing it. **Mathematical Structure:** ``` Schnorr-style proof: - Commitment: A_y = kร—G (random k) - Challenge: c (from hash) - Response: s_y = k + cร—private_key Verification: s_yร—G = A_y + cร—PublicKey If sender doesn't have private_key: Cannot compute valid s_y Proof fails ``` **Source:** `cryptography/crypto/proof_generate.go` - A_y generation ### A_D: Balance Update Proof **Purpose:** Proves the encrypted balance update is mathematically correct. **What It Validates:** ``` Old encrypted balance: E(old_balance) Transfer amount: E(amount) New encrypted balance: E(new_balance) Proves: E(old_balance) - E(amount) = E(new_balance) Without revealing: old_balance, amount, or new_balance ``` **Source:** `cryptography/crypto/proof_generate.go` - A_D generation ### A_b: Balance Commitment Proof **Purpose:** Proves the balance commitment has proper binding and hiding properties. **Properties Ensured:** - **Binding:** Cannot change committed value later - **Hiding:** Cannot determine committed value from commitment **Mathematical Structure:** ``` Pedersen Commitment (textbook form): C = amount ร— G + blinding ร— H Properties: - Cannot find different (amount', blinding') with same C (binding) - Cannot determine amount from C without blinding (hiding) ``` > **DERO's instantiation differs.** The per-ring-member transaction commitment uses each ring slot's **public key** as the second generator rather than a global `H` (`C[i] = ยฑamount ร— G + r ร— pubkey[i]`, see `walletapi/transaction_build.go:152-206` and [Balance Mechanics](/integrity/balance-mechanics.md)). The textbook Pedersen form above is shown as background for the binding/hiding properties; the actual on-chain construction is ElGamal-style with the receiver-pubkey acting as the second generator. The binding/hiding properties carry over; the security argument differs in the details. **Source:** `cryptography/crypto/proof_generate.go` - A_b generation ### A_X: Constraint Proof **Purpose:** Validates additional protocol-specific constraints. **What It Covers:** - Transaction format validity - Protocol rule compliance - Additional cryptographic constraints **Source:** `cryptography/crypto/proof_generate.go` - A_X generation ### A_t: Range Proof **Purpose:** Proves the combined 128-bit value is valid (lower 64 bits = transfer, upper 64 bits = remaining balance) without revealing either value. **This is the bulletproof component:** - Validates both transfer AND remaining balance simultaneously (low and high 64 bits of the packed 128-bit value) - Logarithmic proof size (7 rounds for 128-bit range) - By bulletproof soundness, no prover can construct a verifying proof for a committed value outside the proven range โ€” the cryptographic basis for non-negative amounts **[Detailed explanation โ†’](/integrity/range-proof-integrity.md)** **Source:** the A_t commitment itself is constructed at `cryptography/crypto/proof_generate.go:1120-1121` (a single sigma element `-k_bยทG + k_tauยทH`). The bulletproof input that A_t commits to is built earlier: packing `number := btransfer.Add(btransfer, bdiff.Lsh(bdiff, 64))` at `proof_generate.go:468-471`, and bit decomposition (`number_string` reversal + `aL` / `aR` for-loop) at `proof_generate.go:473-487`. ### A_u: Key Image Proof **Purpose:** Proves the transaction's linking tag (`proof.u`) was correctly derived from the sender's secret key. **From Source Code** (`cryptography/crypto/proof_generate.go:1123-1136`): ```go A_u := new(bn256.G1) // ... build input from transaction-specific data ... point := HashToPoint(HashtoNumber(input)) A_u = new(bn256.G1).ScalarMult(point, k_sk) ``` **What this does:** - Computes a key image by scalar-multiplying a transaction-derived curve point by the secret key nonce - The verifier recovers A_u from `proof.s_sk` and `proof.u` (`proof_verify.go:399-400`) - Binds the proof to a specific (hidden) ring member without revealing which one > **Note on naming:** DERO uses an account model, not UTXO. There are no "outputs" to mark as spent. The A_u proof serves as a key image / linking tag that cryptographically ties the transaction to the sender's secret key within the ring signature framework. --- ## Verification Flow ```mermaid sequenceDiagram participant TX as Transaction participant V as Verifier (Node) participant BC as Blockchain TX->>V: Submit (proofs + responses) V->>V: Recompute challenge hash Note over V: c' = hash(A_y || A_D || ...) V->>V: Verify A_y against c' V->>V: Verify A_D against c' V->>V: Verify A_b against c' V->>V: Verify A_X against c' V->>V: Verify A_t against c' V->>V: Verify A_u against c' alt All proofs valid V->>BC: Accept transaction BC->>BC: Update state else Any proof invalid V->>TX: Reject transaction end ``` **Verification flow** (see `cryptography/crypto/proof_verify.go`): The `Verify()` function (`proof_verify.go:98`) performs all checks in sequence. The key checkpoints are: 1. **Overflow check** (`line 108-111`) -- Reject if fees overflow 2. **Parity check** (`line 136-141`) -- Verify the secret parity is well-formed 3. **B^w ร— A recovery** (`line 162-180`) -- Verify polynomial commitment structure 4. **Challenge hash** (`line 410-425`) -- Recompute `c` from all six sigma components and compare to `proof.c` 5. **Inner product** (`line 457-460`) -- `proof.ip.Verify(hPrimes, u_x, P, o, gparams)` If any checkpoint returns `false`, the entire transaction is rejected. See [Proof Verification Flow](/integrity/proof-verification-flow.md) for the full walkthrough. --- ## Security Analysis ### Attack Resistance | Attack | Why It Fails | |--------|-------------| | **Forge single proof** | Changes hash โ†’ all proofs invalid | | **Replay old transaction** | A_u key image is bound to Roothash (tree state) โ†’ stale proof fails; nonce/height prevents reuse | | **Spend without key** | A_y requires private key โ†’ fails | | **Negative amount** | A_t range proof โ†’ fails | | **Incorrect balance** | A_D validates math โ†’ fails | ### Cryptographic Assumptions **Security relies on:** 1. **Elliptic Curve Discrete Logarithm Problem (ECDLP)** on the bn256 (Barreto-Naehrig) curve -- a pairing-friendly curve also used by Ethereum's precompiles and early Zcash 2. **Random Oracle Model** -- Hash functions behave as random oracles 3. **Decisional Diffie-Hellman (DDH)** -- Underpins the ElGamal encryption used for balance confidentiality ### Why bn256? DERO's proof system requires **pairing operations** โ€” a math operation that pairing-friendly curves like bn256 support and non-pairing curves like secp256k1 do not. This is why DERO and Bitcoin use different curves: they need different capabilities. Bitcoin can do its job without pairings; DERO's bulletproofs cannot. The trade-off: pairing-friendly curves have lower effective security at the same parameter size. For bn256 specifically, analysis of the extended Tower Number Field Sieve (Menezes 2016; NCC Group 2017 reassessment) places effective security at **~100 bits** against discrete-log attacks on the pairing-target field, rather than the ~128 bits originally targeted. **What this means in practice:** ~100 bits remains computationally infeasible for any foreseeable adversary, including well-resourced nation-states. The same analysis applies to every production pairing-based system โ€” Ethereum's bn256 precompiles (EIP-196/197), early Zcash, and others. bn256 has not been broken and is not approaching practical attack. But it is not 128, and these docs name that honestly rather than imply parity with secp256k1. **Breaking DERO's proofs would require:** - Solving ECDLP on bn256 (no known efficient algorithm exists for these parameters) - Or finding a flaw in the underlying constructions (bulletproofs and sigma protocols, published cryptographic literature; DERO's implementation is open for independent review) --- ## Key Takeaways ### What Transaction Proofs Provide | Feature | Benefit | |---------|---------| | **๐Ÿ” All-or-nothing security** | No partial fakes โ€” challenge hash binds all six | | **๐Ÿ”’ Zero-knowledge** | Reveals nothing about transaction | | **โšก Efficient verification** | Logarithmic proof size (7 rounds for 128-bit range) enables fast verification | | **๐Ÿ“ Mathematical guarantee** | Based on proven cryptography | ### The Circular Dependency ``` โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ Proofs โ”€โ”€โ”€โ”€โ”€โ”€โ–บ Hash โ”€โ”€โ”€โ”€โ”€โ”€โ–บ Responses โ”‚ โ”‚ โ–ฒ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ”‚ โ”‚ (circular dependency) โ”‚ โ”‚ โ”‚ โ”‚ Cannot create valid responses without โ”‚ โ”‚ knowing what the final hash will be. โ”‚ โ”‚ Cannot know final hash without all proofs. โ”‚ โ”‚ Cannot change proofs without breaking hash. โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` **The Key Insight:** All six proofs are cryptographically entangled. This isn't just "checking six things" - it's a single interconnected proof system where the validity of each component depends on all others. --- ## Related Pages **Security Suite:** - [Range Proof Integrity](/integrity/range-proof-integrity.md) - Deep dive into A_t - [Proof Verification Flow](/integrity/proof-verification-flow.md) - End-to-end flow - [Negative Transfer Protection](/integrity/negative-transfer-protection.md) - How A_t prevents negatives **Privacy Suite:** - [Bulletproofs](/privacy/bulletproofs.md) - Zero-knowledge range proofs - [Homomorphic Encryption](/privacy/homomorphic-encryption.md) - Encrypted balance operations --- --- title: "DERO Privacy Suite: Complete Technical Guide | DERO Blockchain" description: "Deep dive into DERO's multi-layered privacy architecture including ring signatures, homomorphic encryption, bulletproofs, and transaction privacy mechanisms." keywords: ["DERO privacy", "ring signatures", "homomorphic encryption", "bulletproofs", "transaction privacy", "blockchain anonymity", "privacy technology", "cryptographic privacy", "sender privacy", "DERO security"] date: "2025-10-18" lastUpdated: "2026-01-26" authors: ["DHEBP"] slug: "privacy" canonicalUrl: "https://derod.org/privacy" tags: ["privacy", "security", "cryptography", "anonymity", "technical", "research"] --- # DERO Privacy Suite ## Privacy by Design **Privacy is a spectrum, not binary.** DERO provides strong privacy guarantees while maintaining usability and functionality. DERO doesn't add privacy as an afterthought - it's built into every layer of the protocol, from network communication to smart contract execution. **Core Principles:** - Privacy by default (no opt-in required) - Layered privacy (TLS + anonymity set + homomorphic encryption) with a single verifier-enforced integrity gate (bulletproof soundness + balance proofs) - Mathematical guarantees (proven cryptography, not security through obscurity) - Conscious trade-offs (transparent about limitations) **The Breakthrough:** DERO achieved something no other blockchain has accomplished: combining account-based architecture with strong privacy guarantees through homomorphic encryption. This enables private smart contracts, instant transactions, and encrypted balances - all while maintaining complete privacy. **Naming note:** "Ring signature" is the user-facing name DERO uses for what the source actually implements as an Anonymous Zether-style anonymity-set ZK proof (see `cryptography/crypto/proof_generate.go` and `proof_verify.go`). The user-facing term is colloquial; the construction is not a classical (Schnorr/LSAG/MLSAG) ring signature. ## Privacy Technologies Overview | Technology | What It Protects | Key Benefit | Learn More | |------------|-----------------|-------------|------------| | **Ring Signatures** | Sender identity | Hide among ring_size/2 potential senders (naive guess 1/(N/2)) | [Explore โ†’](/privacy/ring-signatures.md) | | **Homomorphic Encryption** | Amounts, balances | Math on encrypted data (network never sees values) | [Explore โ†’](/privacy/homomorphic-encryption.md) | | **Bulletproofs** | Amount validity | 128-bit combined range proofs (logarithmic size) | [Explore โ†’](/privacy/bulletproofs.md) | | **Account-Based Privacy** | Transaction patterns | Account model + privacy (unique to DERO) | [Explore โ†’](/privacy/account-based-privacy.md) | | **Payload Proofs** | Sender verification | Only YOU can prove you sent (third parties can't) | [Explore โ†’](/privacy/payload-proofs.md) | --- ### Homomorphic Encryption **Math on encrypted data. Blockchain never sees your balance. Ever.** Do math on encrypted balances without ever decrypting them. Your balance stays private. Forever. **The Magic:** ``` E(500) + E(100) = E(600) Network never learns: 500, 100, or 600 ``` **Enables:** Instant balance queries, private tokens, private smart contracts. **[Explore Homomorphic Encryption โ†’](/privacy/homomorphic-encryption.md)** --- ### Account-Based Privacy **The Impossible Combination: Accounts + Privacy + Smart Contracts** DERO's unique architectural achievement: account-based model with strong privacy guarantees. **DERO's Unique Solution:** - Account-based model (simple, fast) - Private smart contracts (unique to DERO) - Target block time set by consensus parameters (BLOCK_TIME = 18s) - Lightweight wallets (no chain scanning required) **[Explore Account-Based Privacy โ†’](/privacy/account-based-privacy.md)** --- ### Bulletproofs **Zero-knowledge proofs that don't reveal amounts.** Proves your transaction values are valid **without revealing what they are**. DERO uses a 128-bit combined range proof that validates both the transfer amount (lower 64 bits) and remaining balance (upper 64 bits) in a single proof. Cryptographically secured by the bn256 elliptic curve discrete logarithm problem. **Key properties:** - Logarithmic-size proof (7 rounds for 128-bit range) - Bulletproof soundness rejects any committed value outside the proven range โ€” including the `uint64` wraparound of a negative โ€” at the verifier, on every node. **[Explore Bulletproofs โ†’](/privacy/bulletproofs.md)** --- ### Ring Signatures **Hide among ring_size/2 potential senders.** Your address is mixed with other members in a ring. Rings are split evenly โ€” half senders, half recipients. The blockchain sees ONE of the sender-half sent the transaction, but cannot determine which one. **Privacy Levels (naive guess):** - 1 in (ring_size/2) chance if no additional information is available (e.g., 1/8 for ring size 16) - Larger rings reduce the naive guess probability **Key Insight:** Ring members' encrypted balances change even as decoys - this is normal behavior, not a bug! **[Explore Ring Signatures โ†’](/privacy/ring-signatures.md)** --- ### Payload Proofs **Only YOU can prove you sent it. Third parties can only guess.** Privacy by design: Only YOU (with your private keys) can prove you sent a transaction. Third parties can only make guesses - exactly as designed for maximum privacy! **The Design:** - Wallet-level convenience tools (not blockchain verification) - Can be faked - by design, for privacy - Third parties cannot definitively prove sender identity **This is a feature, not a bug.** **[Explore Payload Proofs โ†’](/privacy/payload-proofs.md)** --- ## Complete Privacy Documentation **Core Technologies:** - [Ring Signatures](/privacy/ring-signatures.md) - Sender anonymity (2-128 members) - [Homomorphic Encryption](/privacy/homomorphic-encryption.md) - Encrypted balances and operations - [Bulletproofs](/privacy/bulletproofs.md) - 128-bit combined range proofs (logarithmic size) **Privacy in Action:** - [Transaction Privacy](/privacy/transaction-privacy.md) - Complete end-to-end flow - [Account-Based Privacy](/privacy/account-based-privacy.md) - Unique architectural achievement - [Private Smart Contracts](/privacy/private-smart-contracts.md) - Contract code and state variables are PUBLIC; token balances **in user wallets** stay encrypted, transferable peer-to-peer without the contract seeing the amount **Understanding Proofs:** - [Payload Proofs](/privacy/payload-proofs.md) - Wallet-level verification mechanisms --- --- title: "Account-Based Privacy: DERO's Architectural Innovation | DERO Blockchain" description: "Learn why DERO's combination of account-based blockchain with homomorphic encryption creates unique capabilities impossible with UTXO-based privacy systems." keywords: ["account-based blockchain", "DERO architecture", "account privacy", "UTXO vs accounts", "encrypted accounts", "account model privacy", "blockchain architecture", "DERO innovation"] date: "2025-10-18" lastUpdated: "2026-01-26" authors: ["DHEBP"] image: "/assets/account-based-privacy.jpeg" slug: "account-based-privacy" canonicalUrl: "https://derod.org/privacy/account-based-privacy" tags: ["privacy", "architecture", "accounts", "technical", "innovation"] --- # Account-Based Privacy: The Unprecedented Combination **Architectural Breakthrough:** DERO achieves something no other blockchain has accomplished: combining an account-based model with strong privacy guarantees through homomorphic encryption. This enables direct account updates, simple balance tracking, and private smart contracts - all with encrypted amounts. ## What Problem Does This Solve? **The Challenge:** ``` Blockchain needs: โœ“ Account simplicity โœ“ Privacy guarantees โœ“ Smart contract support โœ“ Direct account updates But historically: โŒ Accounts = No privacy โŒ Privacy = Output-based only โŒ Can't have both... or can we? ``` **DERO's Solution:** - โœ… Account-based model (simple, fast) - โœ… Homomorphic encryption (privacy) - โœ… Private smart contracts (unique to DERO) - โœ… Best of both worlds --- ## The Account Model Advantage ### How DERO's Accounts Work **Account Structure:** - Balance is a single value that can be directly updated - Direct query - no need to sum outputs - Simple add/subtract operations - Natural fit for smart contracts - Lower complexity than output-based systems --- ## Why Account + Privacy Is Hard ### The Challenge DERO Solved **The Impossible Problem:** ```mermaid graph TB A["Account Model"] --> B["Needs Persistent Balance"] C["Privacy"] --> D["Needs Encrypted Balance"] B --> E["Problem: How to update E(balance)?"] D --> E E --> F["Challenge 1: E(old) + E(amount) equals ?"] E --> G["Challenge 2: Verify E(balance) >= E(amount)"] E --> H["Challenge 3: Update encrypted balance ciphertexts"] F --> I["Most blockchains: CANNOT solve"] G --> I H --> I I --> J["DERO Solution: Homomorphic Encryption"] J --> K["E(a) + E(b) equals E(a+b)"] K --> L["Works with accounts!"] ``` **Why This Was Thought Impossible:** ### The Challenge **The Account Privacy Challenge** ``` For accounts with privacy: 1. Balance must be encrypted 2. Operations must work on encrypted values 3. Network must verify without decrypting 4. Updates must be direct 5. Must support smart contracts The problem: โŒ How to add E(old) + E(new)? โŒ How to verify E(balance) >= E(amount)? โŒ How to update encrypted balance ciphertexts? โŒ How to do this efficiently? Most blockchains: CANNOT solve this ``` ### DERO's Solution **DERO's Solution: Homomorphic Encryption** ``` ElGamal homomorphic encryption: 1. Encrypt balances: E(balance) 2. Operations work: E(a) + E(b) = E(a+b) 3. Verification via proofs (no decryption) 4. Direct updates (account model benefit) 5. Smart contracts can move encrypted wallet balances homomorphically Enables: โœ“ Account simplicity โœ“ Amount privacy โœ“ Balance privacy โœ“ Smart contract privacy โœ“ Target block-time confirmations โœ“ Simple wallet sync This combination was unprecedented! ``` --- ## Three Key Advantages ### 1. Transaction Confirmation (Target Block Time) **DERO's Flow:** Submit to mini-block system โ†’ account update โ†’ main block target time (BLOCK_TIME = 18s) | Aspect | DERO Account Model | |--------|-------------------| | **Confirmation** | Target block time: 18 seconds | | **Validation** | Simple account update | | **Block Structure** | Mini-blocks + main blocks | | **Finality** | Same-block finality | **Advantage:** Fast confirmation with account model + privacy โœ… **Source:** Target block time is defined by `config/config.go:34` (`const BLOCK_TIME = uint64(18)`). --- ### 2. Simple Balance Checking **DERO's Flow:** Query encrypted balance โ†’ decrypt with private key (no chain scanning) | Step | DERO Account Model | |------|-------------------| | **1** | Query encrypted balance | | **2** | Decrypt with private key | | **3** | See balance locally | | **Time** | No chain scanning required | | **Data Required** | One RPC call | **Advantage:** Balance checks without full sync โœ… --- ### 3. Smart Contract Compatibility **DERO Account Model:** Natural state storage, direct balance updates, contracts can move encrypted wallet balances homomorphically without seeing the amount | Feature | DERO Account Model | |---------|-------------------| | **State Storage** | โœ… Natural (`STORE`/`LOAD` to graviton tree, plaintext) | | **Balance Updates** | โœ… Direct (homomorphic on encrypted wallet balances) | | **Logic Complexity** | โœ… Full support | | **Encrypted Wallet Token Balances** | โœ… Contract can transfer without decrypting the amount | **Advantage:** Rich smart contracts whose **token movements** preserve user privacy (contract logic and state itself are public). --- ## Technical Implementation ### How DERO Manages Encrypted Accounts **Account Structure:** - Address: `dero1qy...` - Encrypted balances stored in Graviton DB - Key: the compressed public key (33 bytes โ€” `tx.MinerAddress[:]` or the pubkey decoded from the bech32 address); the `dero1qy...` bech32 form is only the display encoding. Value: `E(amount)` (ElGamal `(Left, Right)` pair) - Supports multiple assets: DERO, tokens, etc. **Balance Updates:** **Simplified pseudocode** (`blockchain/transaction_execute.go`): ```text // Conceptual flow โ€” see source for actual implementation func UpdateBalance(address, amount): old_encrypted := LoadBalance(address) // E(old) new_encrypted := HomomorphicAdd(old_encrypted, amount) // E(old + amount) StoreBalance(address, new_encrypted) // Save E(new) // Network never decrypts old, amount, or new! ``` --- ## Mini-Blocks and Finality ### How DERO Achieves Fast Confirmation **Mini-Block Architecture:** ```mermaid sequenceDiagram participant U as User participant S as Mini-Block participant M as Main Block participant BC as Blockchain U->>S: Submit Transaction S->>S: Include in mini-block S->>S: Homomorphic Balance Update S->>M: Aggregate to Main Block M->>BC: Confirm (target block time 18s) BC->>U: Final - Privacy Maintained! ``` **Timeline:** | Step | Order | What Happens | |------|-------|--------------| | **1. Submit** | 1 | User submits transaction | | **2. Mini-Block** | 2 | Included in mini-block | | **3. Update** | 3 | Homomorphic balance update | | **4. Main Block** | 4 | Aggregated and confirmed | | **5. Final** | 5 | Transaction final | **Why This Works:** - Single account validation (simple) - Easy parallelization - Fast confirmation - Privacy maintained throughout **DERO combines:** Speed of accounts + Privacy of encryption โœ… --- ## Wallet Synchronization ### Lightweight Clients Possible **DERO Account-Based:** Query encrypted balance to Decrypt with private key = **Seconds** (optional history sync) | Aspect | DERO Wallet | |--------|-------------| | **Required** | Query encrypted balance | | **Time** | Seconds | | **Data** | Minimal (one query) | | **Optional** | Transaction history sync | **Advantage:** Lightweight wallets with full privacy โœ… --- ## Privacy Guarantees **Naming note:** "Ring signature" is the user-facing name DERO uses for what the source actually implements as an Anonymous Zether-style anonymity-set ZK proof (see `cryptography/crypto/proof_generate.go` and `proof_verify.go`). The user-facing term is colloquial; the construction is not a classical (Schnorr/LSAG/MLSAG) ring signature. ### What Account Model Doesn't Compromise ```mermaid graph TB P["Account Privacy"] --> S["Sender Privacy"] P --> A["Amount Privacy"] P --> U["Transaction Unlinkability"] P --> SC["Smart Contract Privacy"] S --> S1["Anonymity-set proof: 1 sender hidden among 8 (ring size 16, 8+8 parity split โ€” the parity assignment itself is cryptographically hidden from observers, see proof_verify.go:130-141)"] A --> A1["Encrypted Balances: Homomorphic operations"] U --> U1["Different Rings: Encrypted amounts"] SC --> SC1["Wallet token balances encrypted; contract state public"] ``` | Privacy Aspect | DERO Account Privacy | |----------------|---------------------| | **Sender** | โœ… Anonymity-set proof (hidden among 8 potential senders at ring size 16) | | **Amount** | โœ… Encrypted (homomorphic operations) | | **Unlinkability** | โœ… Different rings per transaction | | **Smart Contracts** | โš ๏ธ Contract code and `STORE`/`LOAD` state are **public**; what's private is the **token balances in user wallets** that a contract can move homomorphically without seeing the amount (see [Private Smart Contracts](/privacy/private-smart-contracts.md)) | **Result:** Strong privacy guarantees on transfers and balances; contract logic is openly auditable. ### What a verified DERO-PROOF reveals The privacy guarantees above are the **defaults** โ€” what the chain hides from every observer. DERO also gives the sender a per-transaction escape hatch: the **DERO-PROOF** (a.k.a. *DERO proof* or *transaction proof* elsewhere in these docs โ€” same thing, single canonical wire-format string). By sharing the proof string for one specific transaction, the sender lets a verifier confirm what was sent to whom โ€” on-chain equivalent of handing someone a receipt. A verified DERO-PROOF on the public explorer surfaces exactly three fields: | Field | What it reveals | |---|---| | **Receiver address** | The `dero1q...` that was paid. **The sender remains hidden in the ring.** | | **Amount** | Exact DERO transferred, in standard units | | **Memo / decoded payload** | The optional comment field from the transfer, if one was attached | The proof scheme is sender-driven: the sender holds the tx key, runs the proof tool, and hands the resulting string to whoever needs to verify the payment. The verifier resolves it against the on-chain transaction; the chain confirms that the named receiver was paid the named amount. **Source:** `proof/proof.go` (`Prove()` returns `receivers`, `amounts`, `payload_raw`, `payload_decoded`); `cmd/explorer/explorerlib/explorerlib.go` wires the result into the explorer UI; `cmd/explorer/explorerlib/templates/tx.tmpl` renders the verified-proof block as `{receiver} Received {amount} DERO`. Note: scope is one transaction at a time. A proof for tx-A reveals nothing about tx-B, even between the same parties. --- ## Why DERO's Approach Works ### The Account Model Advantage | Feature | DERO Has | |---------|----------| | **Privacy** | โœ… Built-in (homomorphic encryption) | | **Speed** | โœ… Target block time: 18 seconds | | **Smart Contracts** | โœ… Natural support with privacy | | **Balance Check** | โœ… No chain scanning required | | **Complexity** | โœ… Low (simple account model) | | **Wallet Sync** | โœ… Lightweight clients supported | **DERO proved:** You CAN have account simplicity AND privacy! ### What Makes DERO Unique | Aspect | DERO | |--------|------| | **Privacy** | โœ… Built-in from architecture | | **Design** | โœ… Designed for encryption | | **Homomorphic** | โœ… Fundamental to the system | | **Status** | โœ… Proven in production | --- ## Key Takeaways ### What Account-Based Privacy Provides | Feature | Benefit | Impact | |---------|---------|--------| | **โšก Target Block Time** | 18 seconds | Consensus target | | **๐Ÿ” Encrypted Balance** | Query encrypted balance | No sync needed | | **๐Ÿ” Smart Contract Privacy** | Contract state is public; wallet token balances stay encrypted across SC transfers | Unique to DERO | | **๐Ÿ“ฆ Simple Wallets** | Lightweight clients | Easy adoption | | **๐ŸŽฏ Account Simplicity** | One balance per account | Lower complexity | | **โœ… Complete Privacy** | All guarantees maintained | Best of both | ### What It Enables - โœ… **Private Smart Contracts** - Unique to DERO - โœ… **Encrypted Balance Queries** - No blockchain scanning - โœ… **Lightweight Wallets** - No chain scanning required - โœ… **Target Block Time** - 18 seconds - โœ… **Account Simplicity** - Lower complexity - โœ… **Proven in Production** - Working system, not theoretical **Innovation:** DERO demonstrated that privacy with accounts was possible through homomorphic encryption. Accounts can be just as private - while being simpler and faster. --- ## Related Pages **Privacy Suite:** - [Ring Signatures](/privacy/ring-signatures.md) - Transaction anonymity - [Homomorphic Encryption](/privacy/homomorphic-encryption.md) - Balance privacy - [Transaction Privacy](/privacy/transaction-privacy.md) - Complete privacy model **Technical:** - [DERO Wallets](/basics/wallets.md) - Stealth address generation - [Wallet RPC API](/rpc-api/wallet-rpc-api.md) - Integrated addresses **Understanding DERO:** - [DERO Tokens](/basics/tokens.md) - Account-based asset model - [Privacy Features](/privacy/index.md) - Full privacy suite overview --- --- title: "Bulletproofs: DERO's Zero-Knowledge Range Proofs | DERO Blockchain" description: "How DERO's bulletproofs prove amounts are valid without revealing them, using logarithmic-size range proofs and cryptographic protection against negative transfers." keywords: ["bulletproofs", "zero-knowledge proofs", "range proofs", "DERO bulletproofs", "compact proofs", "ZK proofs", "cryptographic proofs", "proof verification", "logarithmic proofs", "negative transfer protection"] date: "2025-10-18" lastUpdated: "2026-01-26" authors: ["DHEBP"] image: "/assets/bulletproofs.jpeg" slug: "bulletproofs" canonicalUrl: "https://derod.org/privacy/bulletproofs" tags: ["privacy", "bulletproofs", "cryptography", "technical", "zero-knowledge"] --- # Bulletproofs: Zero-Knowledge Range Proofs **What bulletproofs prove:** Every transfer carries a zero-knowledge proof that the amount is valid **without revealing what it is**. DERO uses a 128-bit combined range proof that binds both the transfer amount and the sender's remaining balance to non-negative 64-bit ranges in a single proof. ## What Problem Do Bulletproofs Solve? **The Challenge:** ``` DERO needs to verify: โœ“ Amount is positive (not negative) โœ“ Amount is reasonable (not 999 trillion) โœ“ Sender has enough balance But WITHOUT revealing: โœ— The actual amount โœ— The sender's balance โœ— Any private information ``` **The Solution: Bulletproofs** - โœ… Prove combined 128-bit value is valid (transfer + remaining balance, each 64-bit) - โœ… Never reveal the amount value - โœ… Logarithmic-size proof (7 rounds for 128-bit range) - โœ… No trusted setup needed (the bulletproof generators `G` and `H` are derived deterministically from public protocol constants via hash-to-curve โ€” `cryptography/crypto/algebra_pedersen.go:36-37` โ€” so there is no setup ceremony to trust) --- ## How It Works (Simple Analogy) **The Bouncer Problem:** ### Old Way **Show ID (Reveals Everything)** ``` You: "I'm 25 years old" Bouncer: "Show me your ID" Bouncer learns: โœ“ You're over 21 โœ“ Your exact age (25) โœ“ Your address โœ“ Your full name โœ“ Your photo โœ“ Everything else on the ID Disclosure: everything on the ID is exposed ``` ### Bulletproof Way **Bulletproof (Reveals Nothing)** ``` You: "I'm over 21" Bouncer: "Prove it mathematically" Bouncer learns: โœ“ You're over 21 โœ— Your exact age โœ— Your address โœ— Your name โœ— Anything else on the ID Disclosure: only the assertion "over 21" is conveyed ``` **For DERO:** - Bulletproof proves: "Combined 128-bit value is valid (transfer amount in lower 64 bits, remaining balance in upper 64 bits)" - Network learns: โœ… Both values are valid (in [0, 2^64)) - Network learns: โŒ What either value actually is --- ## The Proof Flow ```mermaid flowchart TD A["Alice: Send 100 DERO"] --> B["Pack packed = transfer + balance << 64
(128-bit value bound by one bulletproof)"] B --> C["Bit-decompose the packed 128-bit value
(aL_i, aR_i = aL_i - 1) at proof_generate.go:478-486"] C --> D["A_t commits to range-proof polynomial coefficients"] D --> E["Inner Product Proof folds A_t in 7 rounds (log_2 128)"] E --> F["Assemble Bulletproof
(BA + BS + T_1 + T_2 + that + mu + IP)"] F --> G["Broadcast to Network"] G --> H["Every node runs proof_verify.go: Verify()"] H --> I{Valid?} I -->|Yes| J["Transaction accepted
(amount hidden, range guaranteed)"] I -->|No| K["Transaction rejected at consensus"] ``` **What Network Sees:** - โœ… Commitment (encrypted amount) - โœ… Bulletproof (logarithmic-size proof) - โœ… Proof is valid - โŒ Actual amount (hidden) --- ## Protection Against Negative Transfers The guarantee is cryptographic, not a string-parsing quirk: by the **soundness** of the Bulletproof range proof, no prover can construct a proof that verifies for a committed value outside the proven range. Combined with DERO's homomorphic value conservation, value cannot be created from nothing. DERO packs **two** quantities into a single 128-bit value and range-proves them together โ€” the transfer amount in the low 64 bits and the sender's remaining balance in the high 64 bits โ€” so one Bulletproof binds **both** to non-negative 64-bit ranges (`number = transfer + (balance << 64)`, `cryptography/crypto/proof_generate.go:471`). A "negative" transfer is the `uint64` wraparound of a value near `2^64`. It fails the range proof from both directions: | Attack framing | Why the range proof rejects it | |---|---| | Treat the wraparound as the **transfer amount** | A value near `2^64` lies outside `[0, 2^64)` โ€” the low-64 range bound fails. | | Treat it as **receiving** (so your own balance jumps) | The conservation proof forces a matching decrease; the sender's **remaining balance** goes negative โ†’ wraps โ†’ the high-64 range bound fails. | The protection lives in **verification** (`cryptography/crypto/proof_verify.go`), not generation. The wallet builds the proof in `proof_generate.go`; an attacker controls their own wallet and could patch out any client-side check. The cryptographic guarantee comes from the verifier check that every node runs independently before accepting a block. **Common misconception:** A claim circulates that Go's `BigInt.Text(2)` emitting a `'-'` for negative values "breaks the bit loop" in proof generation, and that this is what stops negative transfers. It does not โ€” the loop is `if b == '1' { โ€ฆ } else { โ€ฆ }`, which silently treats a stray `'-'` as a `0` bit. And for any real transaction the packed 128-bit `number` is positive, so no `'-'` appears at all. The actual safeguard is verifier-side Bulletproof soundness. See [Negative Transfer Protection](/integrity/negative-transfer-protection.md) for the full derivation. --- ## The Six Sigma Proofs DERO uses **six interconnected proofs** that all must pass: ```mermaid graph LR A["A_y:
Secret Key"] --> H["Challenge Hash"] B["A_D:
Balance Update"] --> H C["A_b:
Balance Commitment"] --> H D["A_X:
Constraints"] --> H E["A_t:
Range Proof"] --> H F["A_u:
Key Image"] --> H H --> V{"All Valid?"} V -->|Yes| ACC["Accepted"] V -->|No| REJ["Rejected"] ``` | Proof | What It Validates | Security Level | |-------|------------------|----------------| | **A_y** | Sender has private key | ๐Ÿ”’ Cryptographically secure | | **A_D** | Encrypted balance update correct | ๐Ÿ”’ Homomorphic validation | | **A_b** | Balance commitment valid | ๐Ÿ”’ Binding & hiding | | **A_X** | Additional protocol constraints | ๐Ÿ”’ Protocol-specific | | **A_t** | Range-proof commitment for the packed 128-bit value (`transfer + balance << 64`) โ€” **closed by the inner product proof** below | ๐Ÿ”’ Bulletproof โ€” soundness under DL on bn256 (random oracle model) | | **A_u** | Key image (linking tag) is correctly derived from the sender's secret key โ€” ties tx to the sender within the anonymity-set without revealing which slot is the sender | ๐Ÿ”’ Anti-replay, account-model linking (see [Transaction Proofs ยง A_u](/integrity/transaction-proofs.md#a_u-key-image-proof)) | **All Bound Together:** ``` Challenge hash (c) = hash(A_y || A_D || A_b || A_X || A_t || A_u || ...) If ANY proof fails: โ†’ Challenge hash is different โ†’ Verification fails โ†’ Transaction rejected ``` **Source:** `cryptography/crypto/proof_verify.go:98` โ€” `Verify()` recomputes the challenge hash from all six recovered sigma components (lines 410-425), then closes A_t via the inner product proof at line 457. --- ## Inner Product Proof โ€” Closing A_t The inner product proof is **not a seventh independent check**. It is the recursive closure of the **A_t** bulletproof above: A_t commits to polynomial coefficients of the range-proof relation; the inner product argument shows those coefficients fold consistently with the committed value, proving (with the rest of the bulletproof scaffolding) that the packed `transfer + balance << 64` lies in `[0, 2^128)`. A failed inner product check is a failed A_t โ€” and therefore a failed transaction. There is one bulletproof gate, with two named pieces. ### Recursive Halving โ€” How Logarithmic Scaling Works **The Algorithm:** ```mermaid graph TB A["Start: 128 bits"] --> B["Split in Half
64 + 64"] B --> C["Create Commitments L, R"] C --> D["Challenge x"] D --> E["Fold: 64 bits"] E --> F["Split: 32 + 32"] F --> G["Fold: 32 bits"] G --> H["Continue..."] H --> I["Final: 1 bit"] I --> J["Proof: 7 rounds"] ``` **Iterations:** - Start: 128 elements - Iteration 1: 64 elements - Iteration 2: 32 elements - Iteration 3: 16 elements - Iteration 4: 8 elements - Iteration 5: 4 elements - Iteration 6: 2 elements - Iteration 7: 1 element **Total:** logโ‚‚(128) = 7 iterations **Source:** `cryptography/crypto/proof_innerproduct.go:71` hardcodes `length := 7` for the 128-bit range (note: this lives in `Deserialize`, so the 128-bit range size is fixed at the wire level โ€” an attacker cannot submit a proof of a different range); the verifier closure call is `proof.ip.Verify(...)` at `cryptography/crypto/proof_verify.go:457`. The bulletproof input vector itself is packed at `proof_innerproduct.go:41` (the "7 entries" structure). --- ## Zero-Knowledge Property Explained ### What "Zero-Knowledge" Means **After seeing a valid bulletproof, verifier learns:** | Information | Learned? | Reason | |------------|----------|--------| | **Combined 128-bit value is valid** | โœ… Yes | This is what's proven | | **Transfer and balance each in [0, 2^64)** | โœ… Yes | Implicit from 128-bit structure | | **Exact transfer amount** | โŒ No | Zero-knowledge property | | **Exact remaining balance** | โŒ No | Zero-knowledge property | | **Any bits of either value** | โŒ No | Bits are hidden | | **Any private information** | โŒ No | The proof reveals nothing beyond the validity claim | **Formal Properties:** - โœ… **Completeness:** Valid proofs always verify - โœ… **Soundness:** Invalid proofs never verify - โœ… **Zero-knowledge:** No information leaked --- ## Where Bulletproofs Are Used **Three Core Applications:** | Application | What It Validates | Protection | |------------|------------------|------------| | **Transaction Amounts** | Combined 128-bit value (transfer + remaining balance) | Prevents negative transfers | | **Balance Sufficiency** | Both transfer and remaining balance in [0, 2^64) | Prevents overdrafts | | **Asset (token) transfers via `tx.Payloads[t]`** | Range-proves the same packed value for each non-DERO asset moved in the transaction | Same negative/overflow protection applied per asset payload (note: smart-contract `STORE`/`LOAD` state is stored plaintext in the graviton tree โ€” it is *not* bulletproof-protected) | **All three use the same bulletproof mechanism:** - โœ… Prove value is in valid range - โœ… Never reveal the actual value - โœ… Cryptographic guarantee --- ## Key Takeaways ### What You Get | Feature | Benefit | Impact | |---------|---------|--------| | **๐Ÿ”’ Zero-Knowledge** | Amount hidden from network | Transactions don't leak amounts to observers | | **๐Ÿ“ฆ Logarithmic Proofs** | 7 rounds for 128-bit range | Efficient transactions | | **๐Ÿ” No Trusted Setup** | Pure cryptography | Decentralized security | | **๐Ÿ›ก๏ธ Soundness + Conservation** | No verifying proof for out-of-range values | Negative transfers cryptographically impossible | | **โœ… Proven Security** | bn256 elliptic curve discrete log | Standard discrete log security assumption | ### What You're Protected From ```mermaid graph LR A["Threats"] --> B["โŒ Negative Transfers
Mathematically Impossible"] A --> C["โŒ Invalid Amounts
Range Enforced"] A --> D["โŒ Protocol Violations
Cryptographic Checks"] B --> E["โœ… Secure"] C --> E D --> E ``` **The Bottom Line:** **Verifier-side guarantee:** Every node independently checks the Bulletproof. By soundness, no prover can construct a verifying proof for an out-of-range value. Combined with homomorphic value conservation, negative transfers are cryptographically impossible. **Performance + Privacy:** DERO's bulletproof implementation keeps proofs logarithmic in size while preserving strong cryptographic guarantees. --- ## Related Pages **Privacy Suite:** - [Ring Signatures](/privacy/ring-signatures.md) - Sender anonymity - [Homomorphic Encryption](/privacy/homomorphic-encryption.md) - Amount encryption - [Transaction Privacy](/privacy/transaction-privacy.md) - Complete privacy model **Technical Details:** - [DERO Tokens](/basics/tokens.md) - How bulletproofs secure token balances - [Transaction Structure](/privacy/transaction-privacy.md) - Bulletproof integration **Learn More:** - [Privacy Features Overview](/privacy/index.md) - Full privacy suite - [Private Smart Contracts](/privacy/private-smart-contracts.md) - Contract privacy --- --- title: "Homomorphic Encryption: DERO's Account Privacy Innovation | DERO Blockchain" description: "Technical deep dive into DERO's homomorphic encryption system using ElGamal, enabling encrypted account balances and operations on encrypted data for blockchain applications." keywords: ["homomorphic encryption", "ElGamal encryption", "DERO encryption", "encrypted balances", "additive homomorphism", "partially homomorphic encryption", "blockchain encryption", "encrypted operations", "DERO accounts", "cryptographic commitments"] date: "2025-10-18" lastUpdated: "2026-01-26" authors: ["DHEBP"] image: "/assets/homomorphic-encryption.jpeg" slug: "homomorphic-encryption" canonicalUrl: "https://derod.org/privacy/homomorphic-encryption" tags: ["privacy", "encryption", "homomorphic", "technical", "cryptography"] --- # Homomorphic Encryption: Math on Locked Boxes **The Innovation:** Do math on encrypted balances without ever decrypting them. Your balance stays private. Forever. Even the blockchain never sees it. ## What Problem Does It Solve? **The Challenge:** ``` Blockchain needs to: โœ“ Verify transactions (amounts valid) โœ“ Update balances (addition/subtraction) โœ“ Ensure no double-spending But WITHOUT revealing: โœ— Account balances โœ— Transaction amounts โœ— Any private information ``` **The Solution: Homomorphic Encryption** - โœ… Math happens on encrypted data - โœ… No decryption ever required - โœ… Privacy never broken - โœ… Blockchain can verify without seeing amounts --- ## The Simple Analogy ### Regular Encryption **Locked Safe (Regular Encryption)** ``` You have $500 in a locked safe Someone sends you $100 Normal way: 1. Open safe (decrypt) โ†’ See $500 2. Add $100 โ†’ Now $600 3. Lock safe again (encrypt) Problem: When safe is open, anyone can see $500 Privacy: โŒ Broken ``` ### Homomorphic Encryption **Magic Safe (Homomorphic Encryption)** ``` You have $500 in a magic safe Someone sends you $100 Magic way: 1. Drop $100 through slot in safe 2. Money inside automatically becomes $600 3. Safe NEVER opened Result: Nobody ever sees $500, not even for a second Privacy: amount stays encrypted end-to-end ``` **For DERO:** - Balance is **always** encrypted (safe always locked) - Math happens on the encrypted number - Safe never opens - Blockchain never sees actual balance --- ## How It Works ### The Encryption Flow ```mermaid flowchart TD A["Amount: 100 DERO"] --> B["Pick Random 'r'"] B --> C["Calculate:
L = 100ร—G + rร—P
R = rร—G"] C --> D["Encrypted: E(100) = (L, R)"] D --> E["Looks like random
elliptic curve points"] E --> F["Network sees: E(100)"] F --> G["Network learns: NOTHING"] ``` **The Setup:** ``` Private key: x (your secret) Public key: P = x ร— G (everyone can see this) Generator: G (elliptic curve point - public constant) ``` ### Encrypting an Amount **Conceptual flow** (actual implementation: `CommitElGamal` at `cryptography/crypto/algebra_elgamal.go:44-50`; the numbered steps below are docs annotations, not source comments): ```go // Encrypt 100 DERO (illustrative): // 1. Pick random number 'r' (RandomScalarFixed) // 2. Calculate Left: L = 100 ร— G_value + r ร— P_recipient // 3. Calculate Right: R = r ร— G_randomness // 4. Ciphertext: E(100) = (L, R) ``` | Step | What Happens | What Network Sees | |------|-------------|-------------------| | **1. Pick random 'r'** | Generate random number | Nothing | | **2. Calculate L** | `L = 100ร—G + rร—P` | Random elliptic curve point | | **3. Calculate R** | `R = rร—G` | Random elliptic curve point | | **4. Result** | `E(100) = (L, R)` | Random points (no amount visible) | ### The Magic: Homomorphic Operations **Addition & Subtraction on Encrypted Data:** ```mermaid graph LR A["E(500)
Encrypted"] --> C["Homomorphic
Operations"] B["E(100)
Encrypted"] --> C C --> D["E(500) + E(100)
= E(600)"] C --> E["E(500) - E(100)
= E(400)"] D --> F["Result: STILL ENCRYPTED"] E --> F ``` **The Math:** ``` E(a) = (Lโ‚, Rโ‚) E(b) = (Lโ‚‚, Rโ‚‚) Addition: E(a) + E(b) = (Lโ‚ + Lโ‚‚, Rโ‚ + Rโ‚‚) = E(a + b) Subtraction: E(a) - E(b) = (Lโ‚ - Lโ‚‚, Rโ‚ - Rโ‚‚) = E(a - b) The encrypted result is STILL encrypted! No decryption needed at any step! ``` **Mathematical Guarantee:** Based on the elliptic curve discrete logarithm problem on the bn256 (Barreto-Naehrig) curve. --- ## Transaction Flow: Alice โ†’ Bob **Alice sends 100 DERO to Bob:** ```mermaid sequenceDiagram participant A as Alice participant BC as Blockchain participant B as Bob A->>A: Encrypt: E(100) A->>BC: Send E(100) commitment BC->>BC: Verify: E(500) - E(100) = E(400) BC->>BC: Verify: E(200) + E(100) = E(300) BC->>BC: Check: E(500) + E(200) = E(400) + E(300) BC->>B: Update: E(300) B->>B: Decrypt: 300 DERO received Note over BC: Network never learned:
Amounts, balances, or any values ``` **Teaching abstraction, not literal verifier flow.** The diagram above shows the *intuition* โ€” value conservation across encrypted balances. The actual verifier does not perform explicit ciphertext arithmetic like `E(500) + E(200) = E(400) + E(300)` at consensus. Balance conservation is enforced by the sigma proof structure: `A_b` (one of the six sigma commitments) commits to the balance-update polynomial relation, and the prover must produce a valid proof that the relation holds for the encrypted before/after values. The verifier checks the proof, not the arithmetic. See `proof_verify.go:98` for the actual `Verify()` entry point and `proof_generate.go` for what `A_b` commits to. A common point of confusion: **ring size and amount privacy are independent properties.** The conservation above holds regardless of how many decoys the ring contains โ€” the cryptographic reason amounts stay hidden has nothing to do with how many ring members there are. Whatever the RingSize is set in DERO amounts are never revealed. This is why [ring size 2](/privacy/ring-signatures.md#why-ring-size-2-offers-no-anonymity-set) โ€” which removes *sender* anonymity by design โ€” still leaves the *transferred amount* fully encrypted. The two privacy properties are decoupled. ### What Happens at Each Step ### Before **Initial State** ``` Alice's balance: E(500) = (L_a, R_a) Bob's balance: E(200) = (L_b, R_b) Transfer amount: 100 DERO ``` ### Transaction **Create Transfer** ``` Create transfer commitment: E(100) = (L_t, R_t) This goes in transaction as encrypted 'C' commitment Network sees: Random elliptic curve points Network learns: NOTHING about 100 ``` ### Homomorphic Math **Homomorphic Operations** ``` Alice's new balance: E(500) - E(100) = E(400) (L_a, R_a) - (L_t, R_t) = (L_a - L_t, R_a - R_t) Bob's new balance: E(200) + E(100) = E(300) (L_b, R_b) + (L_t, R_t) = (L_b + L_t, R_b + R_t) No decryption occurred at any point! ``` ### After **Final State** ``` Alice's balance: E(400) Bob's balance: E(300) Network verified: โœ“ Balance conservation โœ“ No negative amounts โœ“ Alice had sufficient balance Network never learned: โœ— Actual amounts โœ— Balances โœ— Any values ``` --- ## Comparison: Traditional vs DERO ### Balance Storage | Aspect | Traditional Blockchain | DERO Blockchain | |--------|----------------------|-----------------| | **Account** | `alice.eth` | `dero1qy...` | | **Balance shown** | `500 ETH` ๐Ÿ‘๏ธ Public | `E(???)` ๐Ÿ”’ Encrypted | | **Everyone sees** | Exact amount | Random bytes (66 bytes) | | **Only owner sees** | Same as everyone | Actual balance (with private key) | | **Privacy** | โŒ Zero | โœ… Complete | | **Balance lookup** | Instant (public) | Instant (encrypted) | **The Difference:** - **Bitcoin/Ethereum:** Your balance is like your bank statement posted on a billboard - **DERO:** Your balance is permanently locked in a safe only you can open ### Blockchain Architecture Comparison | Feature | Bitcoin/UTXO | Ethereum (Account) | DERO (Account + Encrypted) | |---------|-------------|-------------------|---------------------------| | **Model** | Outputs | Accounts | Accounts | | **Privacy** | โŒ Pseudonymous | โŒ None | โœ… Encrypted | | **Smart Contracts** | โŒ Limited | โœ… Yes, public | โœ… Yes, **private** | | **Confirmations** | Slower | Fast | Fast | | **Balance Lookup** | Scan chain | Instant | Instant + private | **DERO = Ethereum's simplicity + Privacy coin encryption** ๐ŸŽฏ --- ## Real-World Applications ### 1. Instant Balance Queries **Traditional Privacy Coin:** ``` 1. Download entire blockchain 2. Scan all transactions 3. Calculate balance from history 4. Wait minutes to hours Result: Slow, requires full sync ``` **DERO:** ``` 1. Query encrypted balance from node (66 bytes) 2. Decrypt with your private key 3. See balance instantly Result: Instant, no chain scanning needed ``` The 66 bytes referenced above are load-bearing โ€” they are literally all a DERO wallet pulls from the network to operate. Captain on the wallet sync model: There is no concept of any master private/secret key on DERO. DERO creates a elgamal balance ciphertext associated to any wallet-account. The private key is NOT broken or distributed among other nodes in any way or form. When user opens wallet, no communication with DERO network except 66 bytes are required. This process is completely done within wallet and is not linked with DERO network. As DERO is account model, Only 66 bytes are required by wallet from DERO blockchain to operate. Blocks & transactions are required to create & maintain history on DERO network. This is why DERO wallets **open in seconds** โ€” to display your current balance the wallet pulls only the 66-byte ciphertext (`GetEncryptedBalanceAtTopoHeight`) and decrypts locally. Captain's quote above is explicit about the split: blocks and transactions *are* required to build and maintain history, so when balance changes the wallet binary-searches to the specific blocks where the change happened (`walletapi/daemon_communication.go` SyncHistory) โ€” but that's bounded by activity, not by chain length. Traditional privacy-coin wallets that linearly scan every block don't have that shortcut. ### 2. Private Token Systems **How It Works:** ```mermaid graph TB SC["Smart Contract"] --> A["Alice: E(1000 tokens)"] SC --> B["Bob: E(500 tokens)"] TX["Transfer 100 tokens
Alice โ†’ Bob"] --> H["Homomorphic Operations"] A --> H B --> H H --> A2["Alice: E(900 tokens)"] H --> B2["Bob: E(600 tokens)"] SC --> V["Contract verifies
correctness"] V --> OK["Valid
Amounts hidden"] ``` **Key Points:** **Source** (verbatim from `tests/normal/multi_deposit_test/asset.bas:11-15`): ```basic // Issue Asset after depositing DERO (Convert DERO to TOKENX) Function IssueAsset() Uint64 10 SEND_ASSET_TO_ADDRESS(SIGNER(), DEROVALUE(),SCID()) // send asset without knowing original balance, this is done homomorphically 20 RETURN 0 End Function ``` The `SEND_ASSET_TO_ADDRESS` DVM function is registered at `dvm/dvm_functions.go:80`; the BASIC sample above is the canonical example contract in the test suite. ``` Result in user's wallet: User's token balance: E(1000) โ† Encrypted, only user can decrypt User's DERO balance: E(500) โ† Also encrypted ``` **Traditional tokens (ERC-20):** Balances public in contract **DERO tokens:** Balances encrypted in user wallets, transferable peer-to-peer ### 3. Private DeFi Operations **Swap Example:** ``` Swap 100 DERO for 500 tokens: Your DERO: E(balance_dero) - E(100) Your tokens: E(balance_tokens) + E(500) Public sees: โœ“ Swap contract called โœ— How much swapped โœ— Who swapped โœ— Resulting balances ``` --- ## Technical Implementation ### The C and D Commitments Every DERO transaction contains encrypted commitments: **C Commitment (per ring member โ€” ElGamal-style, not Pedersen):** ```go // One C[i] per ring slot; pubkey[i] is the slot's public key. C[i] = ยฑamount ร— G + r ร— pubkey[i] // sender slot: -amount; receiver slot: +amount; decoys: 0 // (see walletapi/transaction_build.go:152-206) Where: amount = Transfer amount in atomic units (hidden) G = Pedersen value generator (global_pedersen_values.G) r = Transaction-wide blinding scalar (same r across the ring) pubkey[i] = Ring slot's public key โ€” this is the second generator, NOT a global H Properties: โ€ข Binding: Cannot change amount after creating C[i] (discrete-log hard) โ€ข Hiding: Cannot determine amount or which slot is real from C[i] alone โ€ข Homomorphic on accepted balance: nb.Balance.Add(echanges) at blockchain/transaction_execute.go:239 sums an ElGamal change ciphertext into the receiver's encrypted balance. ``` > **Why this is not Pedersen.** Pedersen uses a fixed generator pair `(G, H)`. DERO's per-ring construction reuses each ring member's public key as the second generator (`r ร— pubkey[i]`), which is what makes the same encryption serve both as an anonymity-set commitment and as a per-receiver decryption hint. The two families share the homomorphic add property; the security argument differs. **D Commitment (shared across the whole anonymity set, not per recipient):** ```go D = r ร— G // single value for the entire payload (one D field on Statement, // see cryptography/crypto/protocol_structures.go:38) Purpose: โ€ข Acts as the public "Right" half of the ElGamal triple โ€ข Combined with the receiver's secret key to recover the shared secret โ€ข Same D for all ring members โ€” the receiver-specific shared key is derived from D plus the receiver's own secret ``` **Together they enable:** - โœ… Encrypted amounts in transactions - โœ… Verifiable without revealing amounts - โœ… Homomorphic balance updates **Source:** `cryptography/crypto/algebra_elgamal.go` โ€” ElGamal encryption implementation. Key entry points: `CommitElGamal` at `algebra_elgamal.go:44` (encryption / commitment construction) and `Add` at `algebra_elgamal.go:69` (homomorphic ciphertext addition). ### Technical Specifications | Aspect | Details | |--------|---------| | **Encryption Scheme** | ElGamal (additive homomorphism) | | **Curve** | bn256 (Barreto-Naehrig) curve | | **Security** | Discrete logarithm problem | | **Commitment Size** | 66 bytes (33 left + 33 right) | | **Trusted Setup** | โŒ None required | --- ## Key Takeaways ### What Homomorphic Encryption Provides | Feature | Benefit | Impact | |---------|---------|--------| | **๐Ÿ”’ Encrypted Balances** | Always encrypted | Perfect privacy | | **โž• Math on Encrypted** | Operations without decryption | Privacy never broken | | **โšก Instant Queries** | No chain scanning | Fast balance checks | | **๐Ÿ” Private Tokens** | Encrypted token balances | Complete privacy | | **โœ… Verifiable** | Network can verify | Security maintained | | **๐Ÿšซ No Trusted Setup** | Pure cryptography | Decentralized | ### What It Enables - โœ… **Private Smart Contracts** - Impossible on other chains - โœ… **Instant Balance Lookup** - No blockchain scanning - โœ… **Encrypted Token Systems** - Private token transfers - โœ… **Private DeFi** - Encrypted swap operations - โœ… **Account-Based Privacy** - First blockchain to achieve this **Architectural Breakthrough:** Account-based blockchains were thought incompatible with strong privacy. DERO proved this assumption wrong through homomorphic encryption, enabling private smart contracts with encrypted balances. --- ## Related Pages **Privacy Suite:** - [Ring Signatures](/privacy/ring-signatures.md) - Transaction anonymity - [Bulletproofs](/privacy/bulletproofs.md) - Zero-knowledge range proofs - [Transaction Privacy](/privacy/transaction-privacy.md) - Complete privacy flow - [Payload Proofs](/privacy/payload-proofs.md) - Prove transfers cryptographically **Technical Implementation:** - [DERO Tokens](/basics/tokens.md) - How tokens use homomorphic encryption - [Private Smart Contracts](/privacy/private-smart-contracts.md) - Contract encrypted balances **Build with Privacy:** - [Token Contract](/smartContracts/token.md) - Private token example - [Wallet RPC API](/rpc-api/wallet-rpc-api.md) - Send private transactions --- --- title: "Understanding DERO Payload Proofs: Privacy by Design | DERO Blockchain" description: "Learn how DERO's two-proof system works, why ring members can show successful verification, and how this intentional ambiguity protects sender privacy through ring signatures." keywords: ["DERO payload proofs", "ring signatures", "transaction privacy", "blockchain privacy", "sender anonymity", "proof verification", "privacy by design", "ring member verification", "DERO security", "anti-spoofing", "proof types", "privacy trade-offs"] date: "2025-10-18" lastUpdated: "2026-01-26" authors: ["DHEBP"] image: "/assets/payload-proofs.jpeg" slug: "payload-proofs" canonicalUrl: "https://derod.org/features/payload-proofs" tags: ["privacy", "proofs", "security", "ring-signatures", "verification", "technical"] --- # DERO Payload Proofs **Privacy by construction:** Only you (holding the private key) can prove you sent a transaction. Third parties can guess but cannot prove โ€” by design, so ring-signature plausible deniability remains intact. *For the integrity angle โ€” why explorer "Verified โœ“" on a payload proof isn't evidence of consensus โ€” see [Proof Types Explained](/integrity/payload-vs-transaction-proofs.md).* **Naming note:** "Ring signature" is the user-facing name DERO uses for what the source actually implements as an Anonymous Zether-style anonymity-set ZK proof (see `cryptography/crypto/proof_generate.go` and `proof_verify.go`). The user-facing term is colloquial; the construction is not a classical (Schnorr/LSAG/MLSAG) ring signature. ## How payload-proof ambiguity works DERO uses **ring signatures** to hide the sender. When you send a transaction, your real sender slot is hidden among ring_size/2 potential senders (rings are split evenly between sender-parity and receiver-parity slots; DERO is account-based, so there are no outputs to hide โ€” only signing positions within the anonymity set), creating **plausible deniability** โ€” observers cannot determine who actually sent the transaction. That ambiguity is what makes payload-proof verification ambiguous. If a third party could verify exactly who sent what, ring signatures would not provide privacy. ```mermaid graph LR U[Your Transaction] --> R[Ring of 16 Addresses
8 sender slots + 8 receiver slots] R --> S0[Sender slot 0
could be sender] R --> S1[Sender slots 1-7
could be sender] R --> YOU[Your Address
hidden in 1-of-8 within your parity role] R --> R0[Receiver slot 0
could be receiver] R --> R1[Receiver slots 1-7
could be receiver] R --> P[Observer cannot tell
which sender slot is real,
which receiver slot is real,
or even which parity is sender vs receiver] P --> PR[โœ… Privacy Achieved] ``` ### How This Compares to Other Privacy Coins | Feature | DERO | Zcash (Shielded) | Bitcoin/Ethereum | |---------|------|-------------------|------------------| | **Ring Signatures** | โœ… 2-128 members | โŒ No rings | โŒ No privacy | | **Third-party Proof** | โŒ Ambiguous (private) | โœ… Transparent (viewkeys) | โœ… Fully public | | **Explorer Verification** | โš ๏ธ Probabilistic | โœ… Exact (less private) | โœ… Exact (no privacy) | | **Sender Privacy** | โœ… Maximum | ๐ŸŸก Opt-in viewkeys | โŒ None | **DERO's privacy model:** Third parties cannot definitively prove who sent a transaction โ€” this is the point of ring-signature privacy. --- ## How It Works ```mermaid flowchart TD A[User submits deroproof] --> B[Extract: amount, address, TXID] B --> C[Calculate: x = amount ร— G + shared_key] C --> D{Check: Does x match any
ring commitment?} D -->|Yes| E[โœ“ Display: Proof Verified] D -->|No| F[โœ— Display: Proof Invalid] E --> G[But this only proves:
โ€ข Address in ring โœ“
โ€ข Math consistent โœ“
โ€ข NOT actual sender โœ—] ``` **What this proves:** - โœ… Address is in ring - โœ… Math is consistent - โŒ **NOT** that this address sent the transaction ## How Ring Signatures Protect Privacy **Ring signatures hide the real sender among decoys (2-128 addresses)** All ring members use identical commitment structures with the **same amount**. This is mathematically required for privacy - if different amounts were visible, you could identify the sender. Rings are split evenly โ€” half the members are potential senders, half are potential recipients. ```mermaid graph LR subgraph Ring["Transaction Ring (16 members, 8 sender slots + 8 recipient slots)"] A0[Address 0
Could be sender] A1[Address 1
Could be sender] A7[Address 7
Could be sender] A8[Address 8
Could be recipient] A10[Address 10
Could be recipient] A15[Address 15
Could be recipient] end A0 -.same amount.-> C[Commitment:
C = amount ร— G + addr] A7 -.same amount.-> C A10 -.same amount.-> C A15 -.same amount.-> C C --> R[โœ… Privacy: Observer
cannot identify sender] ``` **Mathematical Privacy** (actual per-ring construction, `walletapi/transaction_build.go:152-206`): ``` C[0] = ยฑamount ร— G + r ร— pubkey[0] // sender slot: -amount; receiver slot: +amount; decoys: 0 C[1] = ยฑamount ร— G + r ร— pubkey[1] // same r (transaction-wide blinding scalar) ... C[k] = ยฑamount ร— G + r ร— pubkey[k] // observer cannot tell which slot is sender/receiver/decoy ``` Each ring slot's commitment uses that slot's own **public key** as the second generator โ€” this is what makes the same encryption serve both as anonymity-set membership and as a per-receiver decryption hint. **Result:** Plausible deniability for all ring members. This is the standard ring-signature mechanism โ€” observable ambiguity is what protects sender identity. **Technical Note:** When an address is included as a ring member (decoy), its encrypted balance changes due to homomorphic operations, even though the address performed no actions. This is cryptographically required behavior - all ring members' encrypted balances participate in the transaction. Observing encrypted balance changes alone cannot identify the real sender, as this happens for all ring members by design. *Learn more: [Ring Signatures - Encrypted Balance Changes](/privacy/ring-signatures.md#encrypted-balance-changes-for-ring-members)* --- ## Decoded Payload โ€” Receiver's View Only A real transaction carries an encrypted payload (destination address, optional comment, amount) inside the per-ring-member commitment structure. **Only the intended receiver can decrypt that payload** (using their secret key plus the shared `D` ElGamal half โ€” see [Ring Signatures: encrypted balance changes](/privacy/ring-signatures.md#encrypted-balance-changes-for-ring-members)). The table below describes what the **receiver's wallet** sees after successful decryption of *its own* slot โ€” not what a third-party observer sees on chain. | Indicator | What the receiver's wallet shows (after decrypt) | |-----------|---------------------------------------------------| | **Payload** | The plaintext fields the sender embedded for this receiver | | **Decoded** | Address, amount, comment recovered | | **Comment** | The plaintext comment, if the sender included one | | **Metadata** | The fields the sender chose to include | **Third-party observers see encrypted bytes for all 16 ring members identically.** They cannot use payload contents to identify the sender, the receiver, or the real ring slots โ€” every slot looks the same on chain. The "indicators" above are wallet UX after decryption, not chain-level forensic signals. ## What Explorers Can and Cannot Show **This applies to ALL privacy blockchains that use ring signatures** | Check Type | Explorer CAN Verify | Explorer CANNOT Verify (Privacy Protection) | |------------|---------------------|---------------------------------------------| | **Ring Membership** | โœ… Address is in the ring | โŒ Which address actually sent (privacy!) | | **Math Consistency** | โœ… Commitment calculations | โŒ Cryptographic proof of specific sender | | **Transaction Validity** | โœ… Transaction is on-chain | โŒ Which ring member is real | | **Amount Bounds** | โœ… Amount is reasonable | โŒ Proof cannot be for another member | **Why this is correct:** Privacy requires plausible deniability. If explorers could prove the exact sender, ring signatures would be useless. --- ## Why Payload Proofs Can Be Faked The ambiguity that protects sender privacy comes at a cost: **any ring member can generate a verifying payload proof for the transaction.** This is not a defect โ€” it is the visible consequence of how the anonymity-set construction works. The explorer's verification (`proof.go:88-95`) recomputes `amount ร— G + shared_key` and checks for a match against any ring commitment `C[k]`; since `C[k] = ยฑamount ร— G + r ร— pubkey[k]` and `shared_key` is derived from the proof string itself, the equation can be made to fit for any `k` by choosing a compatible `shared_key` (see [Why Ring-Member Commitments Are Indistinguishable](#why-ring-member-commitments-are-indistinguishable) below). If only the real sender could produce a verifying proof, ring-signature privacy would not exist. Third parties cannot use payload-proof verification as cryptographic evidence of *who sent what*. **For the integrity-framed perspective** โ€” why payload-proof "Verified โœ“" in an explorer is not the same as consensus acceptance, and not evidence of chain state โ€” see [Proof Types Explained](/integrity/payload-vs-transaction-proofs.md). --- ## Best Practices **For Users:** - โœ… **Certainty:** Check YOUR wallet with private keys - โœ… **Convenience:** Use payload proofs for general verification - โš ๏ธ **Understand:** Explorers show possibilities, not proof of sender **For Developers:** - ๐Ÿ“š **Educate:** Explain transaction vs payload proofs - ๐Ÿ”’ **Privacy First:** Don't promise definitive sender identification - โœ… **Standard Practice:** Ring signature privacy requires plausible deniability --- ## Technical Deep Dive ### Why Ring-Member Commitments Are Indistinguishable **Privacy Requirement:** If ring-slot commitments had obviously identifying differences (different generator pairs, different randomness sources, missing terms), an observer could: โ†’ identify the sender by inspection โ†’ break ring-signature privacy DERO's construction uses the **same algebraic shape** for every ring slot, with a single transaction-wide blinding scalar `r` (`walletapi/transaction_build.go:152-206`): ``` C[k] = ยฑamount ร— G + r ร— pubkey[k] โ†‘ โ†‘ sender slot: -amount same r for every k receiver slot: +amount pubkey[k] is THIS slot's key, decoy slots: 0 not a global H generator ``` The amount sign and value differ per slot, but the **construction is identical** โ€” an observer sees 16 commitments of the same algebraic form, computed against the same `r`. Without the secret keys, none of them is distinguishable as "the sender's" or "the receiver's." **Result:** Cannot identify sender by commitment inspection **Trade-off:** Any ring member's pubkey can be paired with an arbitrary amount + derived shared key to forge a "valid" payload proof โ€” see [the forgery walkthrough](/integrity/inflation-claim.md#part-3-forge-a-fake-proof-yourself) ### DERO's privacy posture Privacy blockchains make different trade-offs: | Approach | Benefits | Trade-offs | Used By | |----------|----------|------------|---------| | **Privacy by default** | Sender hidden among ring decoys; amounts encrypted | Third parties cannot verify the sender โ€” must use their own wallet | DERO | | **Optional privacy** | User controls disclosure | Privacy only if explicitly used | Zcash | | **Public ledger** | Full transparency | No privacy | Bitcoin, Ethereum | DERO opts for privacy by default. Payload-proof ambiguity isn't a flaw โ€” it's the visible consequence of the ring-signature construction. --- ## The Bottom Line **What payload proofs are, and aren't:** - **They are:** wallet-level display tools. Only you, with your private key, can prove you sent a specific transaction. - **They aren't:** a cryptographic identifier of the sender. Any ring member can generate a verifying payload proof for a given transaction. That ambiguity is the visible consequence of how ring signatures work. Bitcoin and Ethereum explorers show exact senders; DERO explorers show ring members. The trade-off is third-party verifiability for sender privacy. --- --- ## Related Pages **Privacy Features:** - [Transaction Privacy](/privacy/transaction-privacy.md) - How transactions stay private - [Homomorphic Encryption](/privacy/homomorphic-encryption.md) - Why balances are encrypted - [Ring Signatures](/privacy/ring-signatures.md) - Sender anonymity **Use Cases:** - [DERO Tokens](/basics/tokens.md) - Prove token transfers - [Private Smart Contracts](/privacy/private-smart-contracts.md) - Prove SC interactions **For Developers:** - [Wallet RPC API](/rpc-api/wallet-rpc-api.md) - Generate payload proofs - [Daemon RPC API](/rpc-api/daemon-rpc-api.md) - Verify proofs on-chain --- --- title: "Private Smart Contracts: DERO's Token Privacy Innovation | DERO Blockchain" description: "Learn how DERO smart contracts issue tokens that become encrypted wallet balances - enabling private token transfers and rug-pull resistance through homomorphic encryption." keywords: ["private smart contracts", "DERO smart contracts", "private tokens", "encrypted token balances", "DVM privacy", "SEND_ASSET_TO_ADDRESS", "token privacy", "rug-pull resistance", "wallet tokens", "DERO DVM"] date: "2025-10-18" lastUpdated: "2026-01-26" authors: ["DHEBP"] image: "/assets/private-smart-contracts.jpeg" slug: "private-smart-contracts" canonicalUrl: "https://derod.org/privacy/private-smart-contracts" tags: ["privacy", "smart-contracts", "DVM", "tokens", "technical"] --- # Private Smart Contracts > [!CAUTION] > **Critical Clarification:** "Private smart contracts" = **TOKENS ENCRYPTED IN USER WALLETS**, not encrypted state variables. Contract code and state are PUBLIC. Token balances in wallets are ENCRYPTED. ## How DERO Token Privacy Actually Works | Aspect | Traditional SC Tokens | DERO SC Tokens | |--------|---------------------|----------------| | **Contract Code** | ๐Ÿ‘๏ธ Public | ๐Ÿ‘๏ธ Public (auditable) | | **SC State Variables** | ๐Ÿ‘๏ธ Public | ๐Ÿ‘๏ธ Public (totalSupply, etc.) | | **User Token Balances** | ๐Ÿ‘๏ธ Public in contract | ๐Ÿ”’ **Encrypted in user wallets** | | **Token Transfers** | Visible amounts | Homomorphic (encrypted) | ### The key innovation: Once tokens are sent to users via `SEND_ASSET_TO_ADDRESS()`, they become **encrypted balances in user wallets** - just like native DERO. The tokens can then be transferred wallet-to-wallet with full homomorphic encryption, WITHOUT going back through the smart contract. ```basic // Contract can send tokens without knowing balances SEND_ASSET_TO_ADDRESS(user, amount, SCID()) // "send asset without knowing original balance, this is done homomorphically" // Source: tests/normal/multi_deposit_test/asset.bas:13 ``` **Result:** Token balances are encrypted in user wallets, not in the SC state itself. > [!WARNING] > **Current Status:** Type 0 (Open) vs Type 1 (Private with `InitializePrivate()`) distinction exists in code, but appears to primarily affect initialization, not variable encryption. The privacy comes from homomorphic token transfers to encrypted wallet balances. --- ## How It Actually Works ### The Two Storage Locations **Traditional Tokens (ERC-20):** ```solidity // ALL balances stored IN the contract mapping(address => uint256) balances; balances[alice] = 1000; // โ† Stored in contract (PUBLIC) balances[bob] = 500; // โ† Stored in contract (PUBLIC) Everyone can see all balances! ``` **DERO Tokens:** ```basic // Tokens sent TO user wallets (ENCRYPTED) Function IssueAsset() Uint64 10 SEND_ASSET_TO_ADDRESS(SIGNER(), DEROVALUE(), SCID()) 20 RETURN 0 End Function // Result: Alice's wallet: E(1000 tokens) // โ† Encrypted in wallet Bob's wallet: E(500 tokens) // โ† Encrypted in wallet Contract has NO record of individual balances! Only users know their token holdings! ``` ### The Magic: SEND_ASSET_TO_ADDRESS() **What this function does:** ```basic SEND_ASSET_TO_ADDRESS(recipient, amount, asset_id) ``` 1. **Doesn't check** recipient's current balance (can't see it - encrypted!) 2. **Sends tokens** directly to recipient's wallet 3. **Updates wallet** using homomorphic encryption: `E(old) + E(amount) = E(new)` 4. **Contract forgets** - no balance tracking in contract **From source code comment:** > "send asset without knowing original balance, this is done homomorphically" > Source: `tests/normal/multi_deposit_test/asset.bas:13` --- ## Why This Matters ### Problem: ERC-20 Token Privacy ``` Ethereum ERC-20 tokens: โœ“ Contract tracks all balances โœ“ Everyone can query: balanceOf(alice) โœ“ All transfers visible โœ“ Whale wallets identified โœ“ Can track all activity Result: ZERO privacy ``` ### Solution: DERO Token Model ``` DERO tokens: โœ“ Balances in encrypted wallets โœ“ Query returns: E(???) - encrypted bytes โœ“ Transfers use ring signatures โœ“ Whale wallets impossible to identify โœ“ Cannot track activity Result: Complete privacy ``` **The difference:** - **ERC-20:** Bank model (bank tracks all accounts) - **DERO:** Cash model (once tokens leave, contract doesn't know who has what) --- ## Rug-Pull Resistance ### The Security Advantage **Ethereum Tokens:** ```solidity // Tokens controlled by contract balances[alice] = 1000; // Contract owns the data // Malicious owner can: function rugPull() onlyOwner { balances[owner] += totalSupply; // Steal everything } Or: function freeze(address user) onlyOwner { balances[user] = 0; // Freeze user funds } ``` **DERO Tokens:** ```basic // Tokens in USER wallets SEND_ASSET_TO_ADDRESS(alice, 1000, SCID()) // Now alice has E(1000) in HER wallet // Contract CANNOT: // โŒ Take them back // โŒ Freeze them // โŒ See the balance // โŒ Control them // Alice controls private keys = Alice controls tokens ``` **Result:** Once tokens are in your wallet, they're YOURS. Contract can't touch them. --- ## Wallet-to-Wallet Token Transfers ### The Unique Capability **Traditional Tokens:** ``` Alice wants to send 100 tokens to Bob: 1. Call contract.transfer(bob, 100) 2. Contract checks balances[alice] >= 100 3. Contract updates: balances[alice] -= 100 4. Contract updates: balances[bob] += 100 5. Everyone sees the transfer ``` **DERO Tokens:** ``` Alice wants to send 100 tokens to Bob: 1. Create transaction (like sending DERO) 2. Include token asset ID in transaction 3. Use ring signatures (sender hidden) 4. Use homomorphic encryption (amount hidden) 5. Bob receives: E(old_balance) + E(100) = E(new_balance) Contract is NOT involved! Transfer happens wallet-to-wallet! Privacy complete! ``` **This is like physical cash:** - Bank (contract) issues cash (tokens) - Cash leaves bank โ†’ people use it directly - Bank doesn't know who has what anymore - People trade cash without bank's knowledge --- ## Private Token Example ### Complete Implementation ```basic /* Private Token Smart Contract โ€” illustrative. `InitializePrivate()` in the canonical DERO test (`tests/normal/multi_deposit_test/asset.bas:20-22`) is just `40 RETURN 0` โ€” empty body. Its only role is to flip the contract's SC_META_DATA.Type from 0 (Open) to 1 (Private); the function exists for its name, not its body. Any one-time setup (owner, supply, initial mint) is typically done in a separate `Initialize()` or in the calling tx. */ Function InitializePrivate() Uint64 40 RETURN 0 End Function /* Owner/supply setup and asset minting happen elsewhere โ€” shown here as a separate function for illustration. */ Function IssueTokens() Uint64 10 IF LOAD("owner") != SIGNER() THEN GOTO 30 20 SEND_ASSET_TO_ADDRESS(SIGNER(), DEROVALUE(), SCID()) 30 RETURN 0 End Function ``` **What's public:** - โœ“ Contract code (auditable for safety) - โœ“ Total supply (verifiable) - โœ“ Owner address (transparency) **What's private:** - ๐Ÿ”’ Individual token balances (encrypted in wallets) - ๐Ÿ”’ Who owns tokens (wallet addresses + ring sigs) - ๐Ÿ”’ Transfer amounts (homomorphic encryption) - ๐Ÿ”’ Trading patterns (unlinkable) --- ## Real-World Applications ### 1. Private Stablecoins ```basic Function Mint(recipient String, amount Uint64) Uint64 10 IF LOAD("owner") != SIGNER() THEN GOTO 30 20 SEND_ASSET_TO_ADDRESS(ADDRESS_RAW(recipient), amount, SCID()) 30 RETURN 0 End Function ``` **Privacy benefits:** - โœ… User holdings hidden (encrypted in wallets) - โœ… Transfer amounts hidden (homomorphic) - โœ… Cannot identify whales - โœ… Cannot track flows **Transparency maintained:** - โœ… Total supply visible (contract variable) - โœ… Mint function auditable (code is public) - โœ… No hidden inflation ### 2. Private NFT/Gaming Assets ```basic Function IssueItem(recipient String, item_id Uint64) Uint64 10 SEND_ASSET_TO_ADDRESS(ADDRESS_RAW(recipient), 1, item_id) 20 RETURN 0 End Function ``` **Privacy:** - โœ… Who owns which items: Hidden - โœ… Inventory contents: Encrypted - โœ… Trades: Private ### 3. Token Swaps ```basic Function Swap(asset_in String) Uint64 10 DIM rate, amount_out as Uint64 20 LET rate = LOAD("exchange_rate") 30 LET amount_out = ASSETVALUE(asset_in) * rate 40 SEND_ASSET_TO_ADDRESS(SIGNER(), amount_out, SCID()) 50 RETURN 0 End Function ``` **Privacy:** - โœ… Swap amounts: Can be hidden (if sent privately) - โœ… User balances: Encrypted in wallets - โœ… Trading patterns: Unlinkable via ring sigs **Public:** - โœ“ Exchange rate (transparent pricing) - โœ“ Swap function (auditable logic) --- ## Technical Details ### How Token Transfers Work **When contract sends tokens:** ```go // blockchain/transaction_execute.go:237-239 echanges := crypto.ConstructElGamal(tx.Payloads[t].Statement.C[i], tx.Payloads[t].Statement.D) nb.Balance = nb.Balance.Add(echanges) // homomorphic addition of changes // User's encrypted balance updated WITHOUT decryption. // `.Add` combines two ElGamal ciphertexts; `.Plus` (scalar add) is a // distinct method and is NOT what runs here. ``` **Storage structure:** ``` User Wallet Contains: DERO balance: E(500 DERO) // 66 bytes encrypted Token balance: E(1000 tokens) // 66 bytes encrypted Each encrypted balance: Left: 33 bytes Right: 33 bytes Total: 66 bytes ``` ### Comparison with Other Platforms | Platform | Token Storage | Privacy | Rug-Pull Risk | |----------|--------------|---------|---------------| | **Ethereum** | Contract state | โŒ Public | โš ๏ธ High (contract controls) | | **Solana** | Token accounts | โŒ Public | โš ๏ธ Medium (freeze authority) | | **DERO** | User wallets | โœ… Encrypted | โœ… Low (you control keys) | --- ## What InitializePrivate() Actually Does ### The Type System Based on source code analysis: ```go // dvm/sc.go:37-40 type SC_META_DATA struct { Type byte // 0 = Open, 1 = Private DataHash crypto.Hash // hash of SC data tree, anchors all SC state in the meta tree } // blockchain/transaction_execute.go:325-327 if _, ok := sc.Functions["InitializePrivate"]; ok { meta.Type = 1 // Mark as private } entrypoint := "Initialize" if meta.Type == 1 { entrypoint = "InitializePrivate" // Use different init } ``` **What we CAN confirm:** - โœ… Type marker stored in metadata - โœ… Different initialization function name - โœ… Tokens work with homomorphic encryption **What we CANNOT confirm:** - โŒ State variables encrypted differently - โŒ LOAD/STORE returning encrypted values - โŒ Homomorphic operations on contract state **The privacy comes from:** Tokens stored as encrypted wallet balances, NOT from encrypted contract variables. --- ## Key Takeaways **What DERO Actually Provides:** 1. **Encrypted token balances** - Stored in user wallets (66 bytes each) 2. **Homomorphic token transfers** - Send without revealing amounts 3. **Ring signature hiding** - Sender identity protected 4. **Wallet-to-wallet transfers** - No contract involvement after issuance 5. **Rug-pull resistance** - Tokens in YOUR wallet, not contract's control 6. **Public code** - Auditable for security and trust **What DERO Does NOT Provide (Currently):** 1. โŒ Encrypted contract state variables (STORE/LOAD are public) 2. โŒ Homomorphic operations on contract variables 3. โŒ Different storage for Type 0 vs Type 1 (both public) **The Innovation is STILL Unique:** No other blockchain lets you: - Issue tokens from smart contracts - Have them become encrypted in user wallets - Transfer them peer-to-peer with full privacy - Keep them outside contract's control This is the "bank cash model" - once tokens are issued, they're like physical cash that can't be tracked. --- ## Related Pages **Privacy Technologies:** - [Homomorphic Encryption](/privacy/homomorphic-encryption.md) - Encrypted SC balances - [Transaction Privacy](/privacy/transaction-privacy.md) - Private contract calls - [Payload Proofs](/privacy/payload-proofs.md) - Prove contract interactions **Build Private Contracts:** - [DVM-BASIC Guide](/dvm/dvm-basic.md) - Smart contract language - [Token Contract](/smartContracts/token.md) - Private token example - [Assets Exchange](/smartContracts/assets.md) - Private DEX example **Understanding Tokens:** - [DERO Tokens](/basics/tokens.md) - How token privacy works - [DERO Virtual Machine](/dvm/dero-virtual-machine.md) - DVM architecture --- --- title: "Ring Signatures: DERO's Sender Privacy Mechanism | DERO Blockchain" description: "How DERO's ring signatures hide sender identity among groups of 2-128 members, providing plausible deniability through proven cryptographic techniques." keywords: ["ring signatures", "DERO privacy", "sender anonymity", "cryptographic signatures", "plausible deniability", "DERO ring members", "sender hiding", "privacy technology"] date: "2025-10-18" lastUpdated: "2026-01-26" authors: ["DHEBP"] image: "/assets/ring-signatures.jpeg" slug: "ring-signatures" canonicalUrl: "https://derod.org/privacy/ring-signatures" tags: ["privacy", "ring-signatures", "cryptography", "anonymity", "technical"] --- # Ring Signatures > [!NOTE] > **Core Concept:** Your address is mixed with others in a ring of 2-128. Rings are split evenly between senders and recipients โ€” only half are possible senders. The blockchain can't determine which one actually sent. **Naming note:** "Ring signature" is the user-facing name DERO uses for what the source actually implements as an Anonymous Zether-style anonymity-set ZK proof (see `cryptography/crypto/proof_generate.go` and `proof_verify.go`). The user-facing term is colloquial; the construction is not a classical (Schnorr/LSAG/MLSAG) ring signature. ## How It Works ```mermaid graph TB A[Alice Sends 100 DERO] --> R{Build Ring} R --> M1[Member 1
Decoy] R --> M2[Member 2
Decoy] R --> M7[Member 7
ALICE real] R --> M16[Member 16
Decoy] M1 --> S[Create Ring Signature
Proves: ONE of them signed] M2 --> S M7 --> S M16 --> S S --> BC[Blockchain
Cannot determine which] BC --> P[Privacy: Alice hidden
among N/2 potential senders] ``` **Traditional signature:** ``` Alice signs โ†’ Everyone knows Alice sent it โŒ ``` **Ring signature:** ``` [Alice + N-1 others] sign โ†’ ONE of N/2 possible senders sent it, which one? Unknown โœ… ``` --- ## Ring Size Impact | Ring Size | Privacy Level | TX Size (bytes) | Naive Guess Probability | |-----------|---------------|----------------|-------------------------| | 2 | Minimal | 1553 | 1 in 1 (no sender privacy) | | 4 | Low | 2013 | 1 in 2 | | 8 | Medium | 2605 | 1 in 4 | | 16 | Good | 3461 | 1 in 8 | | 32 | Strong | 4825 | 1 in 16 | | 64 | Very Strong | 7285 | 1 in 32 | | 128 | Maximum | 11839 | 1 in 64 | **Note:** Rings are split evenly โ€” half the members are potential senders, half are potential recipients. The naive guess probability is therefore 1/(ring_size/2), not 1/ring_size. Ring size 2 (1 sender slot, 1 recipient slot) provides no meaningful sender privacy. **Sources:** - Ring size limits: `config/config.go:58-59` - Transaction sizes: `README.md` (Transactions Sizes table) ```go const MIN_RINGSIZE = 2 const MAX_RINGSIZE = 128 ``` --- ## Real Example **Transaction:** `4b2ebb476849260f077865756b74248a3ced966628b82eb10cdc56482b852d59` ``` Ring Members (16): 0: dero1qy...83dd4s 1: dero1qy...jssfzr 2: dero1qy...0q74k4 3: dero1qy...tr9wrs 4: dero1qy...qa33r9m โ† Unknown if sender or decoy 5: dero1qy...73jc3d ... 15: dero1qy...9nql7m ONE sent 200,000 DERO Which one? HIDDEN ``` **Blockchain shows (for this example ring):** - โœ“ 8 possible senders (half the ring) - โœ— Amount (encrypted) - โœ— Cannot determine real sender - โœ— Cannot link to other TXs --- ## How Ring Members Are Selected **Source** (`cmd/derod/rpc/rpc_dero_getrandomaddress.go:80-111` โ€” quoted verbatim): ```go account_map := map[string]bool{} for i := 0; i < 100; i++ { k, v, err := balance_tree.Random() if err != nil { continue } v_old, err := balance_tree_old.Get(k) if err != nil { continue } if bytes.Compare(v, v_old) != 0 { continue // docs: balance recently changed โ†’ not a stable decoy } var acckey crypto.Point if err := acckey.DecodeCompressed(k[:]); err != nil { continue } addr := rpc.NewAddressFromKeys(&acckey) addr.Mainnet = (globals.Config.Name == config.Mainnet.Name) account_map[addr.String()] = true if len(account_map) > 140 { break } } // docs: returns up to ~140 candidate addresses; wallet samples ring_size-1 of them. ``` **Why unchanged balances?** - Better decoys (less likely to exclude) - Prevents timing attacks - More plausible anonymity ### Roadmap: polymorphic ring selection The selection algorithm described above โ€” uniform random sampling of recently-unchanged-balance addresses โ€” is the current implementation, not the long-term design. Captain has signaled the wallet layer is targeted for *polymorphic* per-wallet selection logic so that no two wallets pick decoys the same way. Also in free time wallet part will have new/modified code to handle more chain-analysis & some points discussed above. Wallet will have some polymorphic code & algo so that no single or two wallets work & selects ring members in same way single/everytime. Also users will be able to configure this part to their preferences. No timeline has been published. The uniform algorithm above remains in force on Release 142. --- ## The Parity Constraint: How the Ring Is Split The even/odd split between sender and recipient positions is not a convention โ€” it is a hard constraint enforced at both the wallet layer and the cryptographic proof layer. ### The Rule When the wallet shuffles ring positions, it keeps shuffling until the sender and receiver land on indices of **different parity** (one even, one odd). **From source code** (`walletapi/transaction_build.go:79-90`): ```go for { crand.Shuffle(len(witness_index), func(i, j int) { witness_index[i], witness_index[j] = witness_index[j], witness_index[i] }) // make sure sender and receiver are not both odd or both even // sender will always be at witness_index[0] and receiver will always be at witness_index[1] if witness_index[0]%2 != witness_index[1]%2 { break } } ``` The comment in the source says it plainly: sender and receiver must not share parity. One occupies an even index; the other occupies an odd index. ### Cryptographic Enforcement The proof generation encodes this split into two separate polynomial sets โ€” `P` for even-indexed ring members, `Q` for odd-indexed ring members. An observer cannot determine which parity the sender occupies. **Source** (`cryptography/crypto/proof_generate.go:700-723` โ€” code below is verbatim; the `// docs:` lines are docs annotations, not in source): ```go for i := 0; i < N; i++ { var poly [][]*big.Int if i%2 == 0 { poly = P // docs: even indices form one parity group } else { poly = Q // docs: odd indices form the other parity group } // ... math at lines 721-723 uses // poly[j][(witness.Index[0]+N-(i-i%2))%N] (sender side) // poly[j][(witness.Index[1]+N-(i-i%2))%N] (receiver side) } ``` The witness index itself is encoded as an 8-bit string (for ring size 16, m=4 bits per role) that interleaves sender and receiver positions (`proof_generate.go:523`): ```go witness_index := reverse(fmt.Sprintf("%0"+fmt.Sprintf("%db", m)+"%0"+fmt.Sprintf("%db", m), witness.Index[1], witness.Index[0])) ``` This structure means the proof system treats even and odd positions as fundamentally separate roles โ€” an attacker cannot forge a valid proof by swapping one for the other. ### Concrete Example: Ring Size 16 ``` Ring positions: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Parity: E O E O E O E O E O E O E O E O โ””โ”€โ”€ Sender candidates โ”€โ”€โ”˜ โ””โ”€โ”€ Recipient candidates โ”€โ”€โ”˜ (8 even slots) (8 odd slots) (or vice versa โ€” observer cannot tell which) ``` - **8 even indices** (0, 2, 4, 6, 8, 10, 12, 14) โ€” one parity role - **8 odd indices** (1, 3, 5, 7, 9, 11, 13, 15) โ€” the other parity role - The sender is one of the 8 members in their parity group โ†’ probability of correct identification: **1/8 = 12.5%** ### Why Ring Size 2 Offers No Anonymity Set With ring size 2: one even slot (index 0), one odd slot (index 1). The sender occupies one slot, the recipient the other. The parity assignment itself (which parity is the sender's role) is **cryptographically hidden** โ€” the verifier's parity check at `cryptography/crypto/proof_verify.go:130-141` rejects malformed parity but does not reveal the assignment to observers. So an observer sees the two ring members and knows one sent and one received, but cannot tell from on-chain data alone which is which. The reason ring size 2 is listed as "no sender privacy" is not that the parity leaks โ€” it's that there is **no anonymity set within the sender's parity role**: there is exactly one candidate sender (the lone member of that parity), so the sender's identity collapses to the singleton on that side. Any additional out-of-band signal (timing, IP, repeated patterns across transactions, known counter-party relationships) then resolves the pair trivially. Ring size 2 should therefore be treated as no meaningful anonymity, even though the parity itself remains hidden. Captain has stated explicitly that this collapse is **intentional** โ€” ring size 2 is the opt-in mode for transactions where the sender wants to be mathematically provable (audit trails, exchange deposits, KYC reconciliation): This is by design. By this you can prove sender mathematically. This is a feature not a bug. There may be some situations/applications when you need to reveal sender, In that case send TX by setting RingSize to 2. In other words: the table above is correct that ring size 2 provides no sender anonymity โ€” and that is the point. The sender is choosing to be derivable. Note: DERO-PROOF is a separate mechanism โ€” it's a receiver-side receipt that reveals receiver+amount+payload and works at *any* ring size. See [Account-Based Privacy โ†’ What a verified DERO-PROOF reveals](/privacy/account-based-privacy.md#what-a-verified-dero-proof-reveals). ### Verify It Yourself | Protection | File | Lines | |------------|------|-------| | Parity constraint (wallet) | `walletapi/transaction_build.go` | 79-90 | | P/Q polynomial split (proof) | `cryptography/crypto/proof_generate.go` | 700-710 | | Witness index encoding | `cryptography/crypto/proof_generate.go` | 523 | | Ring size limits | `config/config.go` | 58-59 | ```bash git clone https://github.com/deroproject/derohe.git cd derohe sed -n '79,90p' walletapi/transaction_build.go # Parity constraint sed -n '700,710p' cryptography/crypto/proof_generate.go # P/Q polynomial split sed -n '523p' cryptography/crypto/proof_generate.go # Witness index encoding grep "RINGSIZE" config/config.go # Ring size limits ``` --- ## Encrypted Balance Changes for Ring Members When an address is included as a ring member (decoy) in a transaction, its encrypted balance changes even though the address performed no actions. This is **normal behavior** and part of how ring signatures provide privacy. **Source** (`walletapi/daemon_communication.go:863-903` โ€” code below is verbatim; the `// docs:` lines are docs annotations, not in source): ```go if bytes.Compare(compressed_address, tx.Payloads[t].Statement.Publickeylist_compressed[j][:]) == 0 { // docs: this monitored address appears in the ring at slot j. changes := crypto.ConstructElGamal(tx.Payloads[t].Statement.C[j], tx.Payloads[t].Statement.D) changed_balance_e := previous_balance_e_tx.Add(changes) // docs: the encrypted balance ciphertext updates regardless of role // (sender / receiver / decoy) โ€” observers can't distinguish from this. switch { case previous_balance == changed_balance: //ring member/* handle 0 value tx but fees is deducted */ //fmt.Printf("Anon Ring Member in TX %s\n", bl.Tx_hashes[i].String()) ring_member = true case previous_balance > changed_balance: // we generated this tx // ... } } ``` **What this means:** 1. Address with zero balance (never used) is selected as ring decoy 2. Encrypted balance changes due to homomorphic operations 3. This is **by design** - all ring members' encrypted balances participate in the transaction 4. The address didn't send anything; it was just included in the ring **Why this is important:** - Encrypted balance changes don't indicate the address was the sender - Ring members are passive participants in the privacy mechanism - This behavior is cryptographically required for ring signatures to work - Observing encrypted balance changes alone cannot identify the real sender **This is normal ring signature behavior, not a protocol flaw.** --- ## What Ring Signatures Protect | Threat | Protected? | How | |--------|-----------|-----| | **Sender Identity** | โœ… Yes | Hidden among ring members | | **Transaction Linking** | โœ… Yes | Each TX has independent ring | | **Third-Party Attribution** | โœ… Yes | Plausible deniability | | **Transaction Amounts** | โŒ No | Needs homomorphic encryption | | **Network Activity** | โŒ No | Needs TLS/Tor | **Ring signatures = Sender privacy ONLY** For complete privacy: Ring sigs + Homomorphic encryption + Bulletproofs + TLS --- ## Why ANY Ring Member Can Generate Proof All ring members use **same amount** in commitments: ``` C[k] = (amount ร— G) + pubkey[k] C[0] = (200000 ร— G) + addr_0 C[1] = (200000 ร— G) + addr_1 ... C[7] = (200000 ร— G) + addr_7 โ† Same 200000! ... ``` **Result:** Anyone can pick ANY member, calculate commitment, create "valid" proof. **This is privacy working as designed** - you can't identify sender by inspection! *Learn more: [Payload Proofs](/privacy/payload-proofs.md)* --- ## Best Practices **For Maximum Privacy:** - Ring size: 64-128 - Vary transaction timing - Run own node **For Balanced Privacy (Recommended):** - Ring size: 16 - Standard network - Trusted or own node **For Developers:** ```javascript // Let users choose transfer({ ringsize: 16 }) // Example transfer({ ringsize: 64 }) // High privacy transfer({ ringsize: 128 }) // Maximum ``` --- ## Common Misconceptions | Myth | Reality | |------|---------| | "Ring sigs = complete anonymity" | Strong privacy, not absolute. 1 in (N/2) chance | | "Bigger always better" | Trade-off: Privacy vs TX size | | "Ring members know they're in ring" | No - passive selection, no notification | | "Decoys must be online" | No - only their public keys used | | "Encrypted balance change = sender" | No - ring members' balances change by design even as decoys | --- ## Key Takeaways **What ring signatures provide:** - โœ… Sender identity hidden (1 in 1-64, i.e. 1 in ring_size/2) - โœ… Plausible deniability ("might be decoy") - โœ… Transaction unlinkability - โœ… No trusted setup needed - โœ… Proven cryptography **What they don't provide:** - โŒ Amount privacy (use homomorphic encryption) - โŒ Network privacy (use TLS/Tor) - โŒ Absolute anonymity (probabilistic hiding) > [!WARNING] > **Plausible Deniability:** If accused of sending a transaction, you can truthfully say "I might be just a decoy" - and nobody can prove otherwise! --- ## Related Pages **Privacy Suite:** - [Homomorphic Encryption](/privacy/homomorphic-encryption.md) - Encrypted balances - [Bulletproofs](/privacy/bulletproofs.md) - Range proofs - [Transaction Privacy](/privacy/transaction-privacy.md) - Complete privacy model - [Account-Based Privacy](/privacy/account-based-privacy.md) - Stealth addresses **How It Works:** - [DERO Tokens](/basics/tokens.md) - Ring signatures in token transfers - [Transaction Structure](/privacy/transaction-privacy.md) - Ring member selection **For Developers:** - [Wallet RPC API](/rpc-api/wallet-rpc-api.md) - Set ring size in transfers - [DERO Daemon](/basics/daemon.md) - Network anonymity layer --- --- title: "Complete Transaction Privacy: How DERO Protects Your Data | DERO Blockchain" description: "See how DERO's privacy layers work together - ring signatures, homomorphic encryption, bulletproofs, and network encryption protecting every transaction." keywords: ["DERO transaction privacy", "complete privacy", "multi-layer privacy", "sender protection", "amount encryption", "DERO security", "private transactions", "blockchain privacy"] date: "2025-10-18" lastUpdated: "2026-01-26" authors: ["DHEBP"] image: "/assets/transaction-privacy.jpeg" slug: "transaction-privacy" canonicalUrl: "https://derod.org/privacy/transaction-privacy" tags: ["privacy", "transactions", "security", "technical", "guide"] --- # Complete Transaction Privacy > [!NOTE] > **Multi-Layer Defense:** DERO combines ring signatures, homomorphic encryption, bulletproofs, and TLS encryption. Even if one layer weakens, others protect your privacy. ## How Privacy Layers Work Together DERO's privacy is layered. Network encryption (TLS), anonymity-set membership, amount encryption, and zero-knowledge proofs each address a different observer and a different question. They are **not** four interchangeable locks against the same attack โ€” they cover different surfaces. **Naming note:** "Ring signature" is the user-facing name DERO uses for what the source actually implements as an Anonymous Zether-style anonymity-set ZK proof (see `cryptography/crypto/proof_generate.go` and `proof_verify.go`). The user-facing term is colloquial; the construction is not a classical (Schnorr/LSAG/MLSAG) ring signature. **The Flow:** ```mermaid flowchart TD TX[Create Transaction] TX --> L1[Layer 1: Network Privacy] TX --> L2[Layer 2: Sender Hiding] TX --> L3[Layer 3: Amount Encryption] TX --> L4[Layer 4: Zero-Knowledge Proofs] L1 --> P1[TLS Encryption
ISP sees: encrypted blob] L2 --> P2[Ring Signatures
Hides: who sent] L3 --> P3[Homomorphic Encryption
Hides: amounts] L4 --> P4[Bulletproofs
Proves: validity without revealing] P1 --> BC[Blockchain] P2 --> BC P3 --> BC P4 --> BC BC --> R[Result: Complete Privacy] ``` **How They Interact:** When you send a transaction, each layer addresses a different observer at a different stage. Network encryption protects your traffic from ISPs. Anonymity-set membership hides which address sent the transaction. Homomorphic encryption keeps all amounts secret. Bulletproofs prove validity without revealing the underlying values โ€” and, at the integrity layer, **bulletproof soundness is the single cryptographic gate that prevents negative-transfer / wraparound mints**. The privacy layers and the integrity gate are not "defense in depth" against the same attack; they cover different surfaces. **Source Code References:** - Network: `p2p/controller.go` (TLS encryption) - Sender: `cryptography/crypto/proof_verify.go` (ring signatures) - Amount: `cryptography/crypto/algebra_elgamal.go` (homomorphic encryption) - Proofs: `cryptography/crypto/proof_generate.go` and `cryptography/crypto/proof_innerproduct.go` (range proof + inner product) --- ## What Each Observer Sees Understanding what different parties can and cannot see helps illustrate how DERO's privacy layers work together in practice. | Observer | Can See | Cannot See | Why Privacy Maintained | |----------|---------|-----------|----------------------| | **ISP/Network** | Encrypted traffic to DERO | Transaction details, amounts, addresses | TLS encryption hides content from **passive** observers. Caveat: the p2p layer uses `tls.Config{InsecureSkipVerify: true}` with self-signed certs (`p2p/controller.go:398`, cert at `:551`), so an **active** MITM (e.g., a hostile ISP that can intercept and present its own self-signed cert) is *not* defended against by TLS alone โ€” the upstream code itself acknowledges this with the comment `// NOTE: this does NOT protect from individual active man-in-the-middle attacks` at `p2p/controller.go:716`. | | **Blockchain** | Ring (2-128 members), encrypted commitments | Real sender, actual amounts, balances | Ring signatures + homomorphic encryption | | **Chainalysis** | Transaction patterns, metadata | Definitive sender, amounts, proof of sending | Cannot prove specific sender identity | | **Bob (receiver)** | Amount, comment, sender position | Alice's balance, other transactions | Only sees his own transaction details | | **Alice (sender)** | Everything (has private keys) | - | Controls own privacy through wallet | --- ## Real Transaction Example **Alice โ†’ Bob: 100 DERO** ### What Alice Sees ``` Balance: 500 DERO Send: 100 DERO To: Bob Comment: "Coffee" After send: Balance: 400 DERO โœ“ ``` ### What Network Sees ``` TLS-encrypted packet Cannot read: โœ— Who sent โœ— Amount โœ— Recipient โœ— Any details Sees only: Encrypted blob ``` ### What Blockchain Shows ``` Ring: [16 addresses including Alice] Commitments: E(100), E(500โ†’400), E(200โ†’300) Proofs: โœ“ Valid Cannot determine: โœ— Which address is Alice โœ— Amounts (encrypted) โœ— Balances ``` ### What Bob Sees ``` Received: 100 DERO From: Position 7 in ring Comment: "Coffee" Cannot see: โœ— Alice's balance โœ— Alice's other TXs ``` --- ## Privacy at Each Stage ```mermaid graph LR C[Create TX] --> R[Add Ring
16 decoys] R --> E[Encrypt Amount
E balance] E --> P[Generate Proofs
Bulletproofs] P --> N[Broadcast
TLS encrypted] N --> V[Verify
No revelation] ``` | Stage | Privacy Added | Source Code | |-------|--------------|-------------| | **Creation** | Local only | `walletapi/wallet_transfer.go:62` | | **Ring Formation** | Sender hiding | `cryptography/crypto/proof_generate.go` | | **Encryption (ciphertext construction)** | Amount hiding | `cryptography/crypto/algebra_elgamal.go:44` (`CommitElGamal`) | | **Homomorphic addition (during balance update)** | Update encrypted balance without decrypting | `cryptography/crypto/algebra_elgamal.go:69` (`Add`) | | **Proofs** | ZK validation | `cryptography/crypto/proof_generate.go` + `cryptography/crypto/proof_innerproduct.go` | | **Broadcast** | Network encryption | `p2p/controller.go:398` (TLS โ€” self-signed, no client/server auth) | | **Verification** | Homomorphic balance update applied to ciphertexts | `blockchain/transaction_execute.go:239` (`nb.Balance.Add(echanges)`) | --- ## Key Takeaways **What's Protected:** - Sender identity (hidden among ring_size/2 potential senders; naive guess probability is 1/(ring_size/2), e.g., 1/8 for ring size 16) - All amounts (encrypted with homomorphic encryption, never decrypted) - All balances (encrypted at all times) - Transaction linkage (unlinkable, independent rings per transaction) **What's Visible (Necessary for Function):** - Transaction occurred (required for processing) - Ring member list (creates ambiguity, actually protects privacy) - Timing metadata (doesn't reveal transaction details) **DERO's Design:** Privacy over third-party verification. Only you (with private keys) can prove you sent a transaction. Third parties cannot definitively prove sender identityโ€”this is by design. Plausible deniability is a feature, not a bug. > [!WARNING] > **Remember:** Privacy requires ambiguity. If you could prove to others you sent a transaction, your privacy would be broken. Plausible deniability is a feature, not a bug. --- ## Related Pages **Privacy Technologies:** - [Homomorphic Encryption](/privacy/homomorphic-encryption.md) - Encrypted balances - [Ring Signatures](/privacy/ring-signatures.md) - Sender anonymity - [Bulletproofs](/privacy/bulletproofs.md) - Range proofs - [Payload Proofs](/privacy/payload-proofs.md) - Prove your transactions **Understanding Transactions:** - [DERO Tokens](/basics/tokens.md) - Private token transfers - [Account-Based Privacy](/privacy/account-based-privacy.md) - Stealth addresses **For Users:** - [DERO Wallets](/basics/wallets.md) - Send private transactions - [Wallet RPC API](/rpc-api/wallet-rpc-api.md) - Programmatic transfers --- --- title: "DERO Daemon RPC API: Complete Reference Guide | DERO Blockchain" description: "Comprehensive documentation for DERO Stargate daemon RPC API endpoints, with examples for blockchain interaction, node communication, and transaction management." keywords: ["DERO RPC API", "blockchain API", "DERO daemon", "JSON-RPC", "blockchain development", "DERO node API", "cryptocurrency API", "blockchain integration", "DERO integration", "daemon endpoints"] date: "2024-08-26" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/rpc-api.jpeg" slug: "daemon-rpc-api" canonicalUrl: "https://derod.org/rpc-api/daemon-rpc-api" tags: ["rpc", "api", "daemon", "integration", "development", "reference"] --- # Dero Stargate RPC API A RPC (Remote Procedure Call) allows you to call methods/functions on a DERO node remotely. This API enables wallets, explorers, miners, and applications to interact with the DERO blockchain programmatically. **Source:** `rpc/daemon_rpc.go` - All RPC methods verified against Release 142 ## Network Ports | Network | RPC Port | Usage | |---------|----------|-------| | **Mainnet** | `10102` | Production use | | **Testnet** | `40402` | Development/testing | **Source:** `config/config.go:103,123` ## What You Can Do - **Query blockchain data** - Blocks, transactions, heights - **Submit transactions** - Broadcast signed transactions - **Mine blocks** - Get block templates, submit work - **Query smart contracts** - Read SC state, variables, balances - **Monitor network** - Peer lists, mempool, network stats ## Echo Test endpoint to verify that the RPC server is enabled and working well on the daemon side. #### Available parameters | Name | Type | Mandatory | Comment | |------|-----------|-----------|--------------------------| | | []string | true | Array of strings | ```json { "jsonrpc": "2.0", "id": "1", "method": "DERO.Echo", "params": ["Hello", "World", "!"] } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10102/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "DERO.Echo", "params": ["Hello", "World", "!"] }' ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": "DERO Hello World !" } ``` ## Ping Simple Ping request #### Available Parameters No Parameters #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "DERO.Ping" } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10102/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "DERO.Ping" }' ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": "Pong " } ``` ## Get Info Returns all information #### Available Parameters No Parameters #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "DERO.GetInfo" } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10102/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "DERO.GetInfo" }' ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": { "alt_blocks_count": 0, "difficulty": 23467, "grey_peerlist_size": 0, "height": 35995, "stableheight": 35987, "topoheight": 35995, "treehash": "2C4A2F8954EA978104D9F4A4D170256B2531F62C30E52A11517FB6375A0D5F29", "averageblocktime50": 17.63982, "incoming_connections_count": 0, "outgoing_connections_count": 0, "target": 18, "target_height": 0, "testnet": true, "network": "", "top_block_hash": "7ed9939d4c910876ef04312cfefe724d62c18c6b8fb2ab342e9671c511c69b88", "tx_count": 0, "tx_pool_size": 0, "dynamic_fee_per_kb": 0, "total_supply": 0, "median_block_size": 0, "white_peerlist_size": 0, "version": "3.4.106-0.DEROHE.STARGATE+18012022", "status": "OK" } } ``` ## Get Block Returns all the information of the requested block. #### Available parameters | Name | Type | Mandatory | Comment | |--------|---------|-----------|---------------| | hash | Hash | false | Block hash | | height | uint64 | false | Block Height | #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "DERO.GetBlock", "params": { "height": 420 } } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10102/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "DERO.GetBlock", "params": { "height": 420 } }' ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": { "blob": "01010000017e9e872cb1a403010000021f9bcc1208dee302769931ad378a4c0c4b2c21b0cfb3e752629c8e02712cb100000001a46a6856b500000000a063e24bc973c78fd057fec97cacd720000000006bb830fa72959300eff8080400", "json": "{\"major_version\":1,\"minor_version\":1,\"timestamp\":1643337166001,\"height\":420,\"miner_tx\":{\"version\":1,\"source_network\":0,\"dest_network\":0,\"txtype\":2,\"value\":0,\"miner_address\":[31,155,204,18,8,222,227,2,118,153,49,173,55,138,76,12,75,44,33,176,207,179,231,82,96,126,18,210,182,250,100,37,0],\"c\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"s\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"height\":0,\"blid\":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],\"scdata\":null,\"Payloads\":null},\"tips\":[\"6a6856b51e9ffd5b07c6c33ca635d984910f3b7fbbaaaebbb61a99780629e449\"],\"miniblocks\":[{\"Version\":1,\"HighDiff\":false,\"Final\":false,\"PastCount\":1,\"Timestamp\":60980,\"Height\":420,\"Past\":[1785222837,0],\"KeyHash\":\"eec07ce3efc1425bc0ad7e8c72d13b0500000000000000000000000000000000\",\"Flags\":0,\"Nonce\":[2483889374,676653056,2732216833]},{\"Version\":1,\"HighDiff\":false,\"Final\":false,\"PastCount\":1,\"Timestamp\":62337,\"Height\":420,\"Past\":[1785222837,0],\"KeyHash\":\"c3443540c243d11f706b6836d516a95500000000000000000000000000000000\",\"Flags\":0,\"Nonce\":[3502056072,2514737664,4017572356]},{\"Version\":1,\"HighDiff\":false,\"Final\":false,\"PastCount\":1,\"Timestamp\":62614,\"Height\":420,\"Past\":[1785222837,0],\"KeyHash\":\"eec07ce3efc1425bc0ad7e8c72d13b0500000000000000000000000000000000\",\"Flags\":0,\"Nonce\":[1690173257,17121537,3807488]},{\"Version\":1,\"HighDiff\":false,\"Final\":false,\"PastCount\":1,\"Timestamp\":64980,\"Height\":420,\"Past\":[1785222837,0],\"KeyHash\":\"eec07ce3efc1425bc0ad7e8c72d13b0500000000000000000000000000000000\",\"Flags\":0,\"Nonce\":[217232465,1676665600,2733630977]},{\"Version\":1,\"HighDiff\":false,\"Final\":false,\"PastCount\":1,\"Timestamp\":1441,\"Height\":420,\"Past\":[1785222837,0],\"KeyHash\":\"c3443540c243d11f706b6836d516a95500000000000000000000000000000000\",\"Flags\":0,\"Nonce\":[3850142823,974323200,4020130308]},{\"Version\":1,\"HighDiff\":false,\"Final\":false,\"PastCount\":1,\"Timestamp\": 1482,\"Height\":420,\"Past\":[1785222837,0],\"KeyHash\":\"eec07ce3efc1425bc0ad7e8c72d13b0500000000000000000000000000000000\",\"Flags\":0,\"Nonce\":[2897249179,974365696,2734162177]},{\"Version\":1,\"HighDiff\":false,\"Final\":false,\"PastCount\":1,\"Timestamp\":2090,\"Height\":420,\"Past\":[1785222837,0],\"KeyHash\":\"c3443540c243d11f706b6836d516a95500000000000000000000000000000000\",\"Flags\":0,\"Nonce\":[1828815903,1915764736,4020518404]},{\"Version\":1,\"HighDiff\":false,\"Final\":false,\"PastCount\":1,\"Timestamp\":2157,\"Height\":420,\"Past\":[1785222837,0],\"KeyHash\":\"c3443540c243d11f706b6836d516a95500000000000000000000000000000000\",\"Flags\":0,\"Nonce\":[1070759456,3517679616,4023003393]},{\"Version\":1,\"HighDiff\":false,\"Final\":false,\"PastCount\":1,\"Timestamp\":3442,\"Height\":420,\"Past\":[1785222837,0],\"KeyHash\":\"c3443540c243d11f706b6836d516a95500000000000000000000000000000000\",\"Flags\":0,\"Nonce\":[186628109,1413669888,2728168962]},{\"Version\":1,\"HighDiff\":true,\"Final\":true,\"PastCount\":1,\"Timestamp\":11441,\"Height\":420,\"Past\":[1785222837,0],\"KeyHash\":\"a063e24bc973c78fd057fec97cacd72000000000000000000000000000000000\",\"Flags\":0,\"Nonce\":[1807233274,1922405120,4026009604]}],\"tx_hashes\":null}", "block_header": { "depth": 35589, "difficulty": "15743", "hash": "60e7e9f73a4a0f2c1b4a97976150ef6f53f0253f8552c6b2e7e4a010929d8259", "height": 420, "topoheight": 420, "major_version": 1, "minor_version": 1, "nonce": 0, "orphan_status": false, "syncblock": true, "sideblock": false, "txcount": 0, "reward": 0, "tips": [ "6a6856b51e9ffd5b07c6c33ca635d984910f3b7fbbaaaebbb61a99780629e449" ], "timestamp": 1643337166001 }, "status": "OK" } } ``` ## Get Block Header By Topo Height Returns the header of the requested block. #### Available parameters | Name | Type | Mandatory | Comment | |--------|---------|-----------|---------------| | topoheight | uint64 | true | Block Topological Height | #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "DERO.GetBlockHeaderByTopoHeight", "params": { "topoheight": 420 } } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10102/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "DERO.GetBlockHeaderByTopoHeight", "params": { "topoheight": 420 } }' ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": { "block_header": { "depth": 35605, "difficulty": "15743", "hash": "60e7e9f73a4a0f2c1b4a97976150ef6f53f0253f8552c6b2e7e4a010929d8259", "height": 420, "topoheight": 420, "major_version": 1, "minor_version": 1, "nonce": 0, "orphan_status": false, "syncblock": true, "sideblock": false, "txcount": 0, "reward": 0, "tips": [ "6a6856b51e9ffd5b07c6c33ca635d984910f3b7fbbaaaebbb61a99780629e449" ], "timestamp": 1643337166001 }, "status": "OK" } } ``` ## Get Block Header By Hash Returns the header of the requested block. #### Available parameters | Name | Type | Mandatory | Comment | |--------|---------|-----------|---------------| | hash | hash | true | Block Top Hash | #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "DERO.GetBlockHeaderByHash", "params": { "hash": "6a6856b51e9ffd5b07c6c33ca635d984910f3b7fbbaaaebbb61a99780629e449" } } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10102/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "DERO.GetBlockHeaderByHash", "params": { "hash": "6a6856b51e9ffd5b07c6c33ca635d984910f3b7fbbaaaebbb61a99780629e449" } }' ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": { "block_header": { "depth": 35615, "difficulty": "15528", "hash": "6a6856b51e9ffd5b07c6c33ca635d984910f3b7fbbaaaebbb61a99780629e449", "height": 419, "topoheight": 419, "major_version": 1, "minor_version": 1, "nonce": 0, "orphan_status": false, "syncblock": true, "sideblock": false, "txcount": 0, "reward": 0, "tips": [ "886ffd7ca424f8c1ea3cd4f361c0e3fe865205fc669cf2c5f5bfe692e022e177" ], "timestamp": 1643337148002 }, "status": "OK" } } ``` ## Get Tx Pool Returns the list of pending transactions (not included in a block). #### Available parameters No parameters #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "DERO.GetTxPool" } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10102/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "DERO.GetTxPool" }' ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": { "txs": [ "1b527cc1c2c58f59d339873a9a31873507e79b5877afb2e9c9f480ba5360257e", "337db1b7a0da82fe7d800b2b5f7790913a8dfdcc2d331579f14b935934be53df", "3f7aca6ede435296902e362a73ec2f801f6f24f1cf93c69ffe607b7e5a82d8c4", "25ad0a277174063d786c40752ad740514a1f16266932a6650d0f267a164e077c", "c8d2b5a8d6cb97d2fa39e797ed795ede0caa1e5413492af2a9efd61638ff9e17", "38a43e4f188c7bd5c0ce52376a693e156cab71dc6cf0705f3987169969367388", "6f056cae1f2e692ea9e066e3d7703f14484125b2f732b7f31a48481f96299965", "0d6e4a43048f23fcf60ba52720ff8cebbd210ebfaab124d8a1147833b7a237fc", "3a8df3121e63e41a274d201f08bd7e5b1cbbab0b09c71887fcc05f1d758401bb", "8bd83e78bd958c5594039b703a09f72efbfe20367d28eb1e942f2c4f13be0989" ], "status": "OK" } } ``` ## Get Random Address Returns a random list of different DERO addresses registered on the blockchain. #### Available parameters | Name | Type | Mandatory | Comment | |--------|---------|-----------|---------------| | scid | Hash | false | SCID of asset/token | #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "DERO.GetRandomAddress" } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10102/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "DERO.GetRandomAddress" }' ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": { "address": [ "deto1qyyusphxgu67m7ymvn79z0j5av4xsjf9hdf0dvwr0xgf846ae66muqgnks5sr", "deto1qy5tfxzc9sv0wamaacza0uup5330ds6je93wpkn6rgp38z6jjaeqgqqpf524e", "deto1qy92f6p3t5nytfsa3er6t8ecvxn53v7yz952xcxgnme5h8jw67ux2qqnrhstn", "deto1qyh8622rswt9efyzkm00shq5nq5cxaxpznham5g6ajnlw7tvmupf2qgg3f24k", "deto1qyv6sd4s8zrjy8lgp4x8cv4um6wj4x5hn95x85nkdzjdy99qvl062qqyqnc48", "deto1qy4mxumzmgxk94x8aumle2wneuns9pwfh0zu4gs4n4j9yasvdnvdvqqmyhc2r", "deto1qyczrgwkhzmqjhexwqjf9v7crzz6sg8jyx8g3asx2ntxhfjq6htvvqg8e2uxx", "deto1qy06ucenpf397vez8cdxerw3red6uw4l8afj23ezczkzx9cyqnf0sqgpekxa0", "deto1qyvmh00j23h2x0604ft60fujrg2hf25x25mwz7zmhkfv89ectyjqzqqcx2g77", "deto1qyw6f0wkfacudv707rew6ekq4azqsey3whx2tgum4tzs62srejl8zqqaqs3gr", ... ], "status": "OK" } } ``` ## Get Transaction Returns information related to a transaction. #### Available parameters | Name | Type | Mandatory | Comment | |--------|---------|-----------|---------------| | txs_hashes | []Hash | true | TXs Hashes | | decode_as_json | uint64 | false | Decode each tx as json | #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "DERO.GetTransaction", "params": { "txs_hashes": [ "6f056cae1f2e692ea9e066e3d7703f14484125b2f732b7f31a48481f96299965", "3f7aca6ede435296902e362a73ec2f801f6f24f1cf93c69ffe607b7e5a82d8c4" ] } } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10102/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "DERO.GetTransaction", "params": { "txs_hashes": [ "6f056cae1f2e692ea9e066e3d7703f14484125b2f732b7f31a48481f96299965", "3f7aca6ede435296902e362a73ec2f801f6f24f1cf93c69ffe607b7e5a82d8c4" ] } }' ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": { "txs_as_hex": [ "01000003e69902fc9485e50fdea029153c274613ad208c6799e0c862bf8cc6239419deda7286440100000000000000000000000000000000000000000000000000000000000000000000f26b7c2a5c3a9d763ecab209229726dc0a5f4b60243929873f59bf4182ee7041a03089e8cdb0040799ebc9ed5883d7d275f35d40cbd91a77529116d98cc14eff7b5782eb5156c23a39b1e0e3443ff9270db16e1b9efc946a1b54d723a502e1359bdd4c3681b91b508b11cde5f1c96061616e12a237deb71aa21553d26840125c4b1246bf87dd6afbdca9c73ac82b712e550405c303113dbeafa9bab25787d77a3bc3dc9da2d44ce40ce03c5e4952c6379798716690011fecf2c99cab204e39ac077e61b918d2f88eded45c595f64586f9d9cb7da8985a136dc192cc05668d6b9e6dec33963fb76588812348b86c3443540c2d218ddfb7a458a61408bbe3a930dfdbcebadcd6729d3e659cca0ac8c8bb608d92c879ec966cc139aa9c2a7469f302f49a97690ca011dd9f623802d9c47cb1c389296cbdfe11672cadd281358fd918e42dc82bd1c5a0007808b6f9df3722ea2cd1348c53e48b8eef5b7a07dc7ceadef267081f52e765f000f0d391589e70dfdbf10d76f664ed871c05383afc93a020ab973cdd0f9c0fa440117bea4708a833a267b87d634b6126f4f5a4be62f47f669c7eab31021e06378f4000856ba59668257dc115ad5382717b25aba1eee9b48cacff41336373f80fd56a8002a71272d83cd47ef24ace033f47a1bba1f8d22d2cdfb8757862d184f7c500e0d002324735d8b6acc63b649fd958a45a8e66c5151aee9939fdd78c917d48ed5619e0005bd24668cd20f0e9edf0955e3e1bf2a5e9ddd3eae65c7b6447984537cf1acca010cc58e9fe91a70aaf5e7499b51a18dffb1bdd5ddd3693f0789cdaabe99472499010427becbde3e356b7d6510b4c080053bce9a3ffabb968659ff5336386d7bc61600123a58d1e63341d2e4193ad1b4cfdf268828a6165a77a5c82144706c6137fc33011dfa92e61edb832f190334b89fbc4af595b0025b6bbb4f471442754197f1bbad0000a8fbddefeda6114a990e73c98fec8f2d9964bc76a4455bee110a02d938d7de0029ef38242cc8843ac6918a3425db7f288f8fc3634a23d558760a9d299a867eff0124f2105b8160426af4907faf86f0a2996fd25ccc71d6787ee95e7485fc1a23040003e4f445af3db81c59697f029960560a0e6bab0a5c067c54806f74c5676c751916a15b0ff4ccbf61e6b8f9447452f3914a305e1b64816cf24dd6e399ff4e047f011638e26605561f36d122bf63b36d3a611173d51501b8f30bf8180cbfedef1b4a0118529975d3d285220fa60ab2b7515bb67cc9d5eb383093b7f21daf9786166147000927a9f2dc6ec4e57f97f2edfa7aa4ae56c16bc706398293e7af86d1d1d063710126d2ca6b0a4b65f1713f54a50535c7835c98ba57c00d50c706ab847d6558f394000507000ea1ee57e4df8809971519c9ee0a26fb4b4c278bc4d995d8d378835c630118e7775ba54ae56eb569bd32544c804d8dc25b3d0d7c7f12fb35af7621cc2fff000a4219708f8aff0c97e9b78a09f5f38a8a3beb6c98474e8fb2d0c2b30638ea34001b6169e608eaf0896c839e00aae7b4aac2807ac2043dbc170cbf2787f08e4493012900f70bb1e03158b62c7974b453adb65ff333dcbc608c84c6f8c9c0005f34fc0023955a9fdf9c56b425090ef030494acc83bb7386654d86fedba23be66323ecf3010f8e7cedeb37731317ed7f736aca1b6374a88cf16b73ac02cce7eea17c762a7f002abd5fa748a2d0dd22fb7009e9d340634b1ef564f4b5bc91c7901479fc3e74e30015b9f3e2dfc97a3279de2f4e5bccbee8d43545514ce26868db4c8db579a6d1d20007827ae78b2c074436510d75436bd9bb66c766cafe5824c4f5accfced038e64c0021f82d411243884c79481bfd9baa856cc231e771b1b17e1fcae371f42ff42239010f1bcbc0cddac7d3b1ae3cda20e6db83b7599756517e3c8fec4f13e5f7f97187002440277fbcb9d1cb94cd59b49b6a4cbcb1a42208735561a1318b3ab78ff9d1de000dff51722f806a2d5df6196b3a521c47708857b51341001b950db12ce96e2b26010ea6cb87ccc338c38b2307caa4438623f1a14b8d0b8f187a9f80e08c68cda9150006517f26865df7a7819d7d5a1c74ef4fe15d4a54da2d6a8debd382e957c2ea51002098ba0f690059d55df8165af1a55e4798b9bb1daaa937b53c01d4a8cc4b9edb00150fd91deb00ad30e3caadd5669e0fd5d4cc4b59ea35cfc346d18050d1348f630003bc4f527a9a48f929e237fd7fc38cb917855e8fd8169f693e5a8e64113aac3e000c108da5314b747e7c4f757422977fb6237c3be338b1f5d1ba5e03e26b50c1c00002da3ed171d24913ebe897ab2ea667f024c71a5cb7ef1726f30a5cf74af2dc050017804fba37ac116e2c8500ea1a4a18e6cb0c4cd1321807dba586a7c737abe568011a72a5d6dd8d2db136897096aed41c20d7ebbe9d9c586636786a83945bac68c60007ef74facdbf94c0dbce28c5331b2b4db401c81f6bf0dbb6b2208e06b103d847010ab72c8375e59fa9da6d24e2dabd238b5ad10cc8e7243748c030554ac7add51301274b1f9397af3a0256385b00fd05fb406fdae5f4dcacf2af18c70d80072332d0012626fc2c876cb5091fc64950eb82962aa524a197dc8632cfe665a56711f07edb0127878b7e0b43601f305265aeb2870c40c1169e5b18043c7df5c33eae137550bc0017ab6786adadf6a3f63619295c5bd9c19dba3c17635c41552bc68ebbe6fc5a31002845094d3e7125879d1e858360fc0e21e91b29b96a96b7dab9da308b5fe0019d0114b1018d2f9e7c80a13c5ab647c54fa146c3166bb19fbdb5b09ed1dac8b6263d010a1b630a3ce5cd9e9a10b65c98175e8d9f9b2798f35f1f4cca7fdebbdd583e0e01000000000000000000000000000000000000000000000000000000000000000022b2ab9093612713f0b44ae740a34ef0d8f017dd2f54f892e9544b04795574c9276a8cfd17248a823c8016064e17a36804925e565c70a6b9dcee66c2a0839acd2460bd2aa01033fae4b083bfd59130c019b76f7588fb001da0f2810c2a2d4d811ed8d399e2ae59afbee965aa8c57a6cccb6fe5d1d0ed1f1e8b7ac16751dabe1227c537bc6896c90f49dfcf896adc7f4dbfe33bbec3597a5ad1df166b2b032dc4138839236ba09dd1fd6a335e4ba079aa0f74b66eafa30c1bb878386f3b1965022400be697d631b9bb807b9a49cd1031e7ee2c5ede5275ad96d37e81aa858376027489e2133df5e1951bb7a24b2e056f76aea2ffb9ebddd57da0970ac2971a017304bc7cf70d7f8322d53900540a4bf31f9ca311eb23294bf514fff9c87a1bbfc0117aa7e643fe76f43aad249e83c2feecf78fdbd3a1bf3a6036770f4d79114150b012ab7e0aab168908e0ecde7bde67e982d49fdf8de447d48ace141aabcdd91d8150b8668245d59512dd76a96e1c8f96480d2659fa2a1c701e3aaaf0d4601ee148e1f970a11ad5bcd041304bf5052b1432efc1d9416c8b5fa384f6ff749e1dc9ef911b147a25d9fa67c10da5fb3d7bf2fda1ba9a8ba0323771c57efc4211149694b13eac2bd2497ccf624b7c998ba09f797d27a4dc837443c7285b60373aed85c160246409e05eef1b532f1f6936fb546e8cfd9be1c8018655515e5e86bf0980a8b07f20eaaf6ae90526d2472138d176cca1b4a58667ee88b19d6e906b1a0eafdc70153743b0d3bc8ae4405e0f43a430d718574b6cb80ed34bf55417af8c58ffcf2266d86a26dfec8e282f85590898bcae2ff7e3fe32937eb0257fde6d1b38276ae1e8e94d31bd4a2c164053e3a65551a5582d14c26d790cbf5bbc0806241d9b51e002a3e47d15d2e70a0201fa2eb82462a51c16096f7052800da8a9da3220e45054d002f42f205ed9a09ddcb83ed212950f43f9389ee416127b52cb5006a470f5c29f70003ff4bddc6d753e6b087c5d0793148c8476f00be31b1fa64be5bec2b62d2781d011b4738d12826104a3b231f8975ea13f780cb8839d8d0cec7118a8952cce6fab3010025613eccb92dbf0ac99afcd8a626089c543eb0493dde59881c6461cb48d2e900000443901ac6c1254bfb7e61a8f74e095d82c68f099649674f2fd08a63d15f0e001393ecba1ab93b4f29f2e6e482b9b03c279c461f7b81840e26a5a4c1fcabc232002cc839ecaa1a488384811b5dc53008762aaa77630d605ede4f94eaeedbda3062012b05119a9c3961b533f6b1dad8cfb95afa45eda90de84b8ec8c4b4cf95181ca100238b29c579fe319d3e24a9a08433f88fa822a32fcd06c73d8d64a1afc840991c000450d30a9882faeb3c437796cce575a1d463b4a96d196d42eaaab8045afb1fba011be8e17cf5c22173437c96b574be0679c71452c17c7852db8dd75bb5d59a63630005dd000a330ac1068f56b4bf608cae8594c2ecc5b5faa2521218445f713c963700", "01000003e69902fc9485e50fdea029153c274613ad208c6799e0c862bf8cc6239419deda7286440100000000000000000000000000000000000000000000000000000000000000000000f7b00b62bb6ffeaf98ed7f252ea95b76b725fe050de30da128837ce772784dc69314c0a5701e123c83bac704c5fec14b6797e3a3cdcda16b9ed97240b4fe144d217a6243620dbd4a2eac6658efee534f82ebb6b94ee8d57311e5e2b6dc711cb75dbf5f11a82683b2291cff7643179e5b85cb5a5959d3588dfc26d199655f2da8cdad81257750e92bc9009213691481cefe0405c30309467aac2a2afcfb09bf242fac7921f1e82cdb4fada78dfe413d0d75514b1ef401ffb247cded31b2c6aa0ad40e324680c3443540c2149e1766f3a8472dca148bea450a6ba676c12aad51f03ae94fc1cd50e53ce915f54ececcbe67ebc8d8f8ca66ca06c1b3f4c07b218884620bc137492a0cbbce17be2d81c304839c0c53e1dcaa5d3debd0ca8c791c9ea1007bb8c884f70026d8a86d32cb79cec58f531754d31b85ec2b7149601ec918941ddb72d33d8333011d3a935cca64839795bd6016b876843295468de4764bb47147e7eb89ba8f405701014e68061e4573d9b491a8180dfc4411b2b4f5c7384770cb6915a09afb0ffa1e001d1c4a4c60a65c3ed5a4fb15bcd65fd7cfa045ac7db6b575f0f2efe1b3a80be90021d71e008c3bccc73b9f163df173a38d32a1567a6876894030b107a1ad9af0ce000b30b9c2106dc0ef5a1a2a1af46e5b1f68614145cd20367c732cd7281f678053010879409ed3cc903a1faf56e9299c6a2a19030ccb559497def01513e72781a8e90122128ab5550b5639812e1076e2cbae330c027b0b284c794aeada50cee433bc200106e23650a4fcfba8f60be26ae22bc863ca68aaad28feaaeeacfec29314a3664b000193659b96a95f31ec5127885fbc3585ad41cf282c01b519c1c0dcaf1628ec1e0026017814db424c1f594420a1c096ac01c48c3a654ff1541c7c8307203fdf6cee000113e0db3f56326973d51cdf3360e9cdae7972e39c0a7f3325c965e48504c5f00018aeb558aaa3ff41f3358faaebe05b52ed1ff233ec973e8bc621e9daf93edafd0107b116db3401423f4975bb5b9d39a3c06bad79f88df43bc3cc9d701ba2709d25000df70aad6d6bdaea8a3bae6e4dfc829e9356ec79de4a614006504e5365de7a810003e4f445af3db81c59697f029960560a0e6bab0a5c067c54806f74c5676c75192d5e86ed77f82ec40247a6058541888613ff9cedba5b0a2fdc87fc4e11c3dbed001c40b4ee98619123eb930c2684ccb3fa5146148a4da5b1d0898691e6367485ff012b08b0ec699421f84b06445e2a067729bfe64d6f072f3890a7277e3a1f5b792a000837564104fefa546b2e2330134a2a0d873e8fc33254fa54101d125816e2094a012d32ed55941b68d79fbe72de192d908924434c78231804b4d6fb01eecfb7edb1000e19c1613a2d2294549466c850d8729aafbe6c31f2c587450c3e01abe49ecb60002a15f0e4b815276858ff375183f44544dedb68e4ddd1d608c5d338c754807d6c0015a783fb7af458137e1100b2a34cda438c01fa2505c745af8e7845d14ab3efb3000befe5ff87e60c230a0d2e062c678904994ce5d998f720e8e821c458239100b30028a11eaee1e9b54026979d3723994624ed974b12063c7481c20df64160c0372701222c9d06da850263e367493c88bdbfb7f58e612492e19f54a6256d1501d8d987001e3aa30bb94c815072d0bf55563d40631bcc11d0832c8ca6278f96caf97a4249000adb571a55bcdef4a4aefb03304624b6158345e91385d14e0c2af7815c8cf5f7010c6fd971a2c9156e95a1a611a8801e0f7ac630f5403a8d79e74839ad5837cb6f001393112847debc1e51379e9cef1f7170d1e5a37844dfac85cf3c21ddaf431902002967be2102e25853016bd44868c0b573e6cb734659c15bc902089a9b710be6a0000abf40ad280302c64d027488c64fb045565d01fd2b79806e061b02fdd48c258b010067270b6d3bdffcc327606cbcaae0824a5311791a63c52ba5c36687f9d48b8801160bac150b6f73abcba7ca95297d9171699526e163dc800e2c51bd8d0a8a599f002e1504db4acba7cd8e36fb5abd2f2711240f02e382cd86b86fd9c25c14ee2c82012bb3ad75755bfb1257681ea4e8922cb77be35e95c4decd63b806fdfa3cd0902001115ecbcf1893b678df2ac70e600d031edaea8f22d7355965ccb5b02d844599ee001c4346a94088c351b48a4edfa4f2a42e4639d5ca77eadb113e6d4e11d5b84a83000359411a2c0cf7de244b4da2e4daf39d4ea9e4c1d0ba33bf755722d37d59efaf000833020cc0992588cf23ba7021c27d6eecd38917bd9f79fd3be3b29271bc73a6001175b41061df0baf57c82cdfe7222bf2322946a938e3320c8244e4ca5c21c612011ce87c2842bd8d1f5c2b7790e05395036350d89ce1b8d522e036e3be7c5855a2012be1a30de449f9a431025d38023a3596db63f9ea6a9bbdbdaa057a8b03079dd501005334ebf3ceb5028561c401dc971d6dcd10803bd7ad7c2c61516f6e8c6d13880015be77d1d0b878ac03cd2e766aa3a2517a157ce29c69b3f73dd55f600849390a0121d54ddeda9cd0938812a7e71aa9b195d19427ca635865cc0bd34e3fb0215f67011b6585ee33f5082b1164a6f8ca27448b616c614d32d9feb7eb06ed341049a52f0022941d16396895ec0c7fd4268497986cc466ef4eedec5453a29fec6bbaf171250023a361d8a6f836e5bc3fc9e2e56194a67fc6ed735707ae09587b2e35d495411a01084c39a1c2444da2f7459c107f403c2ad4770aab683f0b3b64e8c469230ef828011992cbb72047cbc8dd240700152e7051ebdff5f3b74d083384afdb04af215765010caa33c30a9542fd0c8f7d8dee6ec8ff0f899dbef5f5dd994f2e27c18ba53ee3000000000000000000000000000000000000000000000000000000000000000000103ffd6f8a27ed37431f145f4ea498063816b4948ff098f3ddc67b5b2653707d138c6bf2ea9a4718b0a50510b0124b75d24da9a9a07de08847416ab67ab75be3015115995367f4e81f3adb383e3cd7146f770fd3a63bdd9130621b84d17b208c018c80857b89283879764ab8f1ae16b2448621776513c0df487db9e336706a7e1c19a0c127ebf7762f5ee4f334aaa287c2a1af74471d88a22c45cf3348fa16952c30b32fc87990c5b6b9bb2795c85770dc07e541cf94aa7f357442f3ca08c8bb2aba3ed10ef9a8ef1cd20996853384190c4dc79095a91517be60c0d955c2f85e1b22da5326c2b88059b312f7b91b58f52cbf6d84df34834f7d044c7be6a13f041f690b83a6fac06dc6f0cbd7f2c4171aa426951382efbceec9853cdfb566005e00220e6871c0abb720c5b5466d9ab532d6b73797c82e6b570ce0b2d6d151dc154f012ce3e99fe03ea2787f781ba07b27ab73ab84c483762382ff1b69a54def410ad71536278c84543bbd1b5df2441d2078033ff200274d214e1fe602da99c44ca4d80ce6d41d3bb685763c787b4eadd06637eb33a4ab5f8ebcaefa2d23badfd6711a15f024315d03dfb65c01e2ded515109aaa19c56a788d6b81e52311c2113a42af293e1537d5a919ad8f3536602897f553ae8ca2342509815d8091d3099ef67b0014b6e179f0184e79dae1fb5f93e6d16b7ba99603aacd72dee1435b2d0a63dac10eaa5f6e82463a303708008c6d5ce83e1be8a88b0f4e0dc3c274ef1f35dda00b195e0fb94356ff1e390874fb7884866ee511315d348e3dd31b1b1741230ced7e2e3fb65a21ef0577ad6290bd41c94f539d7e613ed3868c80471ae5507876f06a2bd977607ffe9b66c929d8c978b2ab050d911389f35cd23962bbdcb07575ea4b0011932f82346cf49ee903c24acbec4373c6a6e24aed1d2ba6708656eb81affa12002817723dc1ce5f67c680e1742e0290620a4e689e309e664b44ed7fdd3d15d5460102f1cfc9cbb7d9fdb1b1e21480ed229b030fd9293bbd648753903fecfafda2a60128a29cf179688988929e8304ecdfdf1f7d5098cd88ce4b66ca2927cdbf9ebc3c002c861382f359b88d72b281adb8229539c6e7f622f75da274fa1a1ee3cecb1abf0022c07f8f152c80cbd6680533693fe0e76acab8ce4670696573f93f714aa369dc013041371db94160e159d725769ddf0d328745fb2af0a736fd2e8969876dd19662011c8c36dfa032c52f0c3442b7d9695b50d51dcd975d6374e6df1224e276462f6c001dddcfd90e2fbc717135f29af6387daaef87fa791249890d338d644e4532669f000bded5a6a000e08e4797154f5d9137f0e7fde06b0c84217d6c3e06f07eecf2990017f99e2e47bcc0ca0dd2ab1e170e0f828c30408869d9dc46ae75459918fceba700108598f111b389d27e110051a763382cc5ea3f396ae21b6970063a3cac17794b0126030ff863e81e5bbd10f3d434b0490d0a792f1ca50dcf419efdb6b366e364bf01" ], "txs": [ { "as_hex": "", "block_height": 36074, "reward": 0, "ignored": false, "in_pool": false, "output_indices": null, "tx_hash": "", "valid_block": "e286bd3cedfbfaecbbc327f4cb5b1f5457053f322acdd177d6ff55cb6e897e7f", "invalid_block": null, "ring": [ [ "deto1qy2cl36z7rwqsrp9mqf3jf0lj6hxrvmt98dp6uq2zeathn00rv4rqqgwwwq6y", "deto1qy2u9j4c3tv3exmmdd5za82f2gg6dqmaptmxat640ssvwca3zmxajqg67z4sv", "deto1qyxwhayh9hc230g7dqtl76yhpj754dd7uh4kgptd4ya29538u4v8wqgvrfdt4", "deto1qy56vq7gfrhv2jrgjpcrsd65vsgpf7qpz6c0h03wy5ke9fumewkyuqgxshj8c", "deto1qysxfqq9aweksl80wnnxf9n4eqwzxgt9d2uezp2h7rqz5kf2cj5gyqg3pg7eh", "deto1qykz0y7k86fpgymege4uy2zzxmehhzqun9u6azs46ze9adwamupk5qg4j9lvt", "deto1qyywdf79xhw9kmljtef786rx8j6q7tg3uakvgjgvsz7dw5kuxfexjqgm6e2yj", "deto1qyz8umf02tjzkxy2d7alhq2h7xsf6zsuapvy5m4kn67pqrpgc2er6qg6x6d0n", "deto1qyynts8afn6fyxslpn7r420c5hehudwyncjgm6r2yfm5t3s370cuwqgn4j6x2", "deto1qy04yamzkg64ndsc9u3knuknszed6hmxxtmrx6x387dq4r2hr7tezqq9md6rq", "deto1qyyemtmskcpjn3fhguvn0yuquvkasjh5fxwqgk9zk5mn4x0fp7t06qgr7fkdr", "deto1qy0ehnqjpr0wxqnknyc66du2fsxyktppkr8m8e6jvplp954klfjz2qqdzcd8p", "deto1qy9gs9c683903sgc3cna60fwzuka6r4qgdennpreev60z6rsdw0zkqgy47zwm", "deto1qy8z4awcnhnp624ma0fznkpj433wnl75hu47fx73287mk5vy2ga3wqgj9gtla", "deto1qy0cx6faws9ypd7aw3500x93v8t8dgdwfsqmy8sqtsaa844ldgn2wqq0e70le", "deto1qykhpc3ksq7c39sdvguuv02s62q0elcugr4fwnywhg8cnkkch29ryqqyvtq8g" ] ], "signer": "", "balance": 0, "code": "", "balancenow": 0, "codenow": "" }, { "as_hex": "", "block_height": 36074, "reward": 0, "ignored": false, "in_pool": false, "output_indices": null, "tx_hash": "", "valid_block": "e286bd3cedfbfaecbbc327f4cb5b1f5457053f322acdd177d6ff55cb6e897e7f", "invalid_block": null, "ring": [ [ "deto1qyxjcz77he9njxkm2rvd469hlv88yhp3mwwmem5d46jj3lpr6w03wqq8e27rg", "deto1qyhvwyjkgmsg40hkau4csh0ksn4qm072uz0jr75gf45lqmdpxah2kqqrp8s4r", "deto1qyptptr294w6aa38220um5as08krppx6de0qjk7mu5rdfelfn97h5qg6lfd0v", "deto1qy0ehnqjpr0wxqnknyc66du2fsxyktppkr8m8e6jvplp954klfjz2qqdzcd8p", "deto1qyt26zg5csas4h3a88dtqxgny6rlyfdr27jx335x94syjxn652f25qggmlag4", "deto1qyye8v2zfdmpn9vsd98yflmghwgk90tpcrkfpeds645rvfsxvx5jzqq6ezejl", "deto1qyr4pxj7qlxc62j3u7dxdpjgl7vjgmkcf5rwack9dm97etc8fjvx2qq83pmye", "deto1qyr0rgqkh0r679ezp6znwgdyxkzlvq50jazuj3r5yslwkt7rssc4jqq78qwmq", "deto1qy00rwqzshtn98nz6h42k39230k0v5gzkvp7ms83w49zn09s2tes5qguwuhpp", "deto1qyww4r64c4t02qzs8w3cpfw28kfjnrrnth9flk4jped64ynslq8uvqge6hnd4", "deto1qyyj99tnmng4mrk6r9n8kx8zyympm9ljkd07jujhhjudrw3e2nwrkqqc9k29f", "deto1qyy86yhmx8mr3343dnlk9kc9gec3qek028t4xfdhxhk0ymhy88qzuqgyw9tgn", "deto1qy4qyujjy02ayrxs8pgq0rk00n845sqk6dha8jdgp5358v86aqcngqqhld7yr", "deto1qy598uhhf9kgdqlyz4aag7gzrjfeged48m8z9mccrf8yn0ufm8auzqggcyydd", "deto1qyddyeqfnzg2lwgseuefhpl4564rp2d6p5zf9ud0uj7sepmsxnyhgqq7xdkxz", "deto1qyjlw2w4kkfrs6yt4v62tv2zntlvjth435fsuzqafw2yvxt4ae7y6qggjcl4f" ] ], "signer": "", "balance": 0, "code": "", "balancenow": 0, "codenow": "" } ], "status": "OK" } } ``` ## Send Raw Transaction Broadcast a transaction on the DERO network. #### Available parameters | Name | Type | Mandatory | Comment | |--------|---------|-----------|---------------| | tx_as_hex | string | true | TX in hex format | #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "DERO.SendRawTransaction", "params": { "tx_as_hex": "01000003d39a02c1295e6cbaf9f98ed67ba0e6a06eb26b3c5d27fa83e0bd070a058c539d21da5d01000000000000000000000000000000000000000000000000000000000000000000000160678916fcfcb943bf579de316406d1dae91b0799701c38aba61129daa92c662074e559ea4165e259e261aaf4e80262398dfc3b0561a63f5c3da356cadfcb9932efb8e0db977e23c82c4f1c0b6014bf1bbb71b91d9d584bb7de5bddaa80a2a8dd9bf12bfd06ef252fab44884c683e0dc92262ead552b1c6dbc513fedaa59929fd5eb21c80d4a8bf44b346d9cd0a667e40404c3031b970faa7e70d5050842ad3c88679852a8f27b6a5afbec1fb8ad000bd189802200dc9e48d5452ec98e05beb43b51056a57c719ab7ec3443540807a908374c64207008c095ed633722a97c95073398e48de0076fec58f96fe3cd2ecb8d385086fb91e8c9c5028d6b6b5a48a432b8f7ac6c43e31eff39396a2074d8af19b7ab4154f01008c0798cf91f0892c4d8246743386fbf617f72a985634e0059a12eaec24a61001016b05ed80daf1e9580f2ccc66081c3765201f9e6ac230a2b7667a0bba427dc6002d7a9f01ff25296b171e036c9c68053d7de826b180323224417126de0fd0748501238b3a1dc5dbe62de9f0488264ee46c39c08925e2cb68f7b6dc60d8aecbb68620002c66dd5c29de5e9adab3bd7f268f64269e1e96921eeb9637505414c790c0a65011e4020fdc76b7a4a6fad84d0fe875cbd38fa7e816585b639d8c3032aca1b3064010e380630678bcc957c4a1cc8e57d2df9fe7996b98dabd42cf1c49eaa8625e1b80119eb616138a8c3606a3bc1f9a0052eaedf6f50ac4158ad2c42074ff02c3ef786001394a47cf5cfc88b357eb50c88d8f1554f9cd5f1fc00cfd54c35d3664e9c27ce00010990641ed8bea313d3201aa9a1b7dbde6e18376e07df73cdea1b5d1c11309c0122e645671fb85d7e8dc79729cb147a4fb534d17981d4d5d576f965492f3745f0001aecdcae49756e90d99500c31514f8e0421cc7678499dd7d6b8ea393cf3b29ef0116b78b380109adbe63d8597aac8a7d2d92ff655c93432ff70a2eacb5e5d75ae4011227aa289afebbbb5ed5d55cc988f39a818f46b75a6b804ebbe47ff021d0c032002442d20d3b09f99317d36dff5b4dd26b4832c0bd158814f9329506a257c235e800d516c08b48be26167e83850a13e0b3b07a1ff9c92aea0403ed60da213726b9371c815b9607b3f2ac78b8f4aacfbeadf7f7a800751ac231447b17606200b6eb0f01191641ed48d79ce5a064fdacfe40061de65b8c0d7aea1fae353b1effc7f2a2ac00270e2ac0dc68e423d1868f5cac869d64d94702ee9e772ef5fd52b4612ead6f5a0003a1c3d496a186a1a72cfe3078e88168ff326473b8af785b254aa124c69064e400163d332d26ea2e7f66022bd963c4163a6f205d44e35ac83eea7d5a0f1236f09c0023f155555baa1083840831c538443e2805966ab97c8ec333435ac7ab58a979fe002f4b9c816d0c5dfc46b6b507028dd967ba0574f6f3f3503c8cfefca4bd88be7300007ccba7bd0cf11585241ba0e573ab5fbcc159220bfb4669de2cd3d11b9ac8a60020369d2d52fd9c8997c6bd384c3627b03da0cc0c2d2f5aa4b0c74a330192f4c2012278d29396e1c6bfaeb67626da24ec117429f4d207ddd2b0632cb09d12652ec10101e3a4ff8846e1655b007195e1b6d800b4c62a88173d4328002d39f673809954001031c5badf10560137006f3e24fa54b27298109f45802311f72682f8416daf870017f293c47a044b8950bb2432f13aabce8d2778e06acbc77b7ff5c0f9fcf19a0d01192e4f040dade991bfccb215e86d43f6d1dcfdba6b990901fc0803205971a8630100c8de7797ac2233659edad98015d4b09fd72795c88b7e72abe67332b6dfe419011b4b31bb8f4839e93470fdf6466cfeebb71e8268fc4eee7e1fc18c693db1b0ee010635360ad6bc1ac35171de94f599ff94b5b99bb8cbcb752c0d8bf814dcb17bf3011d0e8b621bb2d2ccf391b98afe47b113c135357f5704729a7424eb7d43d692ce0028c2ed7d17398ec2c7430b48d95e5b4641ba9aa09d938aee68a156aa708db4b7012db0d18235dbf4800a23edda7f53a433cb6a7df84a0b5cc4c1e810c4f0a2bd8201034aad9debd087e6b816ac31e8233d08ba685bde235a5f794f908405398c12ee0016d5d080eb4042680548d29f8730198051a9dccd0996d40c5a13b6949f14e4910025f28597f07d17439457e9e41a5c7f7daabbc134f6228be485f452461d5b996701220584b24e5a87af99109c460b2052df26f15e631ef8c36f18004ffd7a71a519002ae7670e81dc479985dd0caa0cb08f2128307b43aea07a6d3c5ab84aa648a5a70004ef828ddc623cb574e87065a5d7c3006597716c910190a866969dfea37c30d600249fb654c861c3688c2898fed0aac1fac075b6478146e3fb99d34ccaf790a21d0012a06b85562f201047ed922fe938e72069e4a25f0cc5782b1aec718c0bce46ea002e0dae8b0fe9e50fbe0ba74c6e0565212fddefef7053529cad2747978265f8a8011c140a7bc045eb496e520b4bd08e9dbdf18b9a1bbf6733be4248442d10a9fb0500302c870c17f7ef67e711df82b6603b30603694e188024fa41a14fada846d8ba9012db86e12e976195f38cba6915f7228c2e98fe0a266df942e7174e3f528ddb1d00102222e91f9a9e91904b17d64977352c93e5ac2f6e1d694041f7863ead356f5ee011f4e1eeef0606a9ae6d87562ed0f81dc0402d327102471c4b9dbb3fa3651ba09010e42adcbf49d9050d82ecaa5c40a9c9858aa0f97976cc593de7141d9aacc0a6c00200be9027f39b0dadb36df2114f3a7605a90347e3625304e290d83841365fa2a0011da530bc17fb6e3c5fcd5291fb286c9b52b943a1c93f68b7ac220ff9b008f170000000000000000000000000000000000000000000000000000000000000000000eab3f99967f03bb3a3b1e689145e406155d4c9e027a1206a1cc972f1003be5612eea86bea3b0ee07dafbc2610fe9c71bdeccead3ba0a2702f5da0d89d084f2c053f0931828d42aec32cd555d5d81639005192e5903da3c23218938c7c3dc918227a34fb4889a56ea461988da95aeca6e17dbf5865696fbe738bd7033f51f0b40346b290197557ac24db3e9281f0fedf01110dfeb4daf4d71163de652dc8b2b61778b5e0bd4f45541b35c62923b99b53c3b94f1478dd81708e14112e152e489e2c1c4c580d3e35a9f0693449a0af566deb3f32340373c023ffa6c9ff8d91f80d07af281574a4822870a05678b41d97c4a9b35541e6940f0120b9d47fc4bb2b2003e95bd2ec3c63245602f21808a875ba0d1028ca3e7869b6c6682a7125c1f2ff011ece8eb96ff3e0e9af0947749056b806e554fde39f475f0ca2211cf9198058a4002703f5443f1886e1caf60f775b6431bc948e4b0e2b76f56a8fc8c29da23caded041917938e845f826ddc5f2ec6aca0a985e6f6c98ea0cbc51f9429e2616500e20605af191eac7bd2696409d65dcbf3108079ec1f6bd5f9601b43dd3b58304d9d205b1ef7b34578d80236c0615ac79f69fcc7c92491bbbd3130cc22e8f0ea1fd21d2d5bfc8da06e2ba48acf70477d1cfefa7165a0804166027f0945faa85057cc236797a65ada0329e7de91712b4974fd83bb99ea97042788bfde4b8b9b5f1b251f6853fc4ffbdff382b24f209d4357099ea1c0d0c383dfd7f03d64bb7bff199406aae7f59190862d36ebefe8d011825bc663c6731f6397d5019f00055a3f80b71ab3b3813d5d509d89432a722ee789db88ca86c86fa76d6224b7eb3c5e66822b1e57f77674481d0a3a7252d47c4da5feab251db1b0b146620a9d271ca951c33f001080c18c31919d2de622fe0170824cc31ecaedd90d8214afcf47a7486474d65200153ade04144d5c29e2e0d6003fcf160bec90d79a42afcb4fe230bc695ce956ba001f4b437e4531531b85e326ccdf160e87408454ecd811fd41a51cc7a9585700df01092a076eebb6fb76ae2443dd7f007fe8edc4c7f54a1bdf48e8e5ae59ca513a9901205d75965eb434dd10e8425ff82d7f6695d4cf0b97507e800c3e3d59a60b83f3002d1496857827c872a53a792e86a74da252f12316972cfadbb2afcfa40a2883790108ccf31a2fdd88201361a0d4313a98a0272173132d1fa3d9bf018f35a7b439b701301da927ac71fea5a0024920ecbadd76f5f05f06b2d8e6874ae9a5348316585b002806c45af761489705e347dcc764ab531fbd7205c36c15f44ad1b633a609dda3000a40291cb5b71269ce0535a8b81ee3440e3db8208e4dd2af38c6591121c6a6560127f8dbc559ca73ecc28c0df0f38b7991bd348121cf5c111c4c505b019d5ef8de0018aae0f6ef38795ec5bac7e55ac5e580599a95043bc57ecc4930d2e1279269b2001c77bc717a5a1788e6157bf937e3f089ec9e27b0a7ab4eab11c25eec1918045300" } } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10102/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "DERO.SendRawTransaction", "params": { "tx_as_hex": "01000003d39a02c1295e6cbaf9f98ed67ba0e6a06eb26b3c5d27fa83e0bd070a058c539d21da5d01000000000000000000000000000000000000000000000000000000000000000000000160678916fcfcb943bf579de316406d1dae91b0799701c38aba61129daa92c662074e559ea4165e259e261aaf4e80262398dfc3b0561a63f5c3da356cadfcb9932efb8e0db977e23c82c4f1c0b6014bf1bbb71b91d9d584bb7de5bddaa80a2a8dd9bf12bfd06ef252fab44884c683e0dc92262ead552b1c6dbc513fedaa59929fd5eb21c80d4a8bf44b346d9cd0a667e40404c3031b970faa7e70d5050842ad3c88679852a8f27b6a5afbec1fb8ad000bd189802200dc9e48d5452ec98e05beb43b51056a57c719ab7ec3443540807a908374c64207008c095ed633722a97c95073398e48de0076fec58f96fe3cd2ecb8d385086fb91e8c9c5028d6b6b5a48a432b8f7ac6c43e31eff39396a2074d8af19b7ab4154f01008c0798cf91f0892c4d8246743386fbf617f72a985634e0059a12eaec24a61001016b05ed80daf1e9580f2ccc66081c3765201f9e6ac230a2b7667a0bba427dc6002d7a9f01ff25296b171e036c9c68053d7de826b180323224417126de0fd0748501238b3a1dc5dbe62de9f0488264ee46c39c08925e2cb68f7b6dc60d8aecbb68620002c66dd5c29de5e9adab3bd7f268f64269e1e96921eeb9637505414c790c0a65011e4020fdc76b7a4a6fad84d0fe875cbd38fa7e816585b639d8c3032aca1b3064010e380630678bcc957c4a1cc8e57d2df9fe7996b98dabd42cf1c49eaa8625e1b80119eb616138a8c3606a3bc1f9a0052eaedf6f50ac4158ad2c42074ff02c3ef786001394a47cf5cfc88b357eb50c88d8f1554f9cd5f1fc00cfd54c35d3664e9c27ce00010990641ed8bea313d3201aa9a1b7dbde6e18376e07df73cdea1b5d1c11309c0122e645671fb85d7e8dc79729cb147a4fb534d17981d4d5d576f965492f3745f0001aecdcae49756e90d99500c31514f8e0421cc7678499dd7d6b8ea393cf3b29ef0116b78b380109adbe63d8597aac8a7d2d92ff655c93432ff70a2eacb5e5d75ae4011227aa289afebbbb5ed5d55cc988f39a818f46b75a6b804ebbe47ff021d0c032002442d20d3b09f99317d36dff5b4dd26b4832c0bd158814f9329506a257c235e800d516c08b48be26167e83850a13e0b3b07a1ff9c92aea0403ed60da213726b9371c815b9607b3f2ac78b8f4aacfbeadf7f7a800751ac231447b17606200b6eb0f01191641ed48d79ce5a064fdacfe40061de65b8c0d7aea1fae353b1effc7f2a2ac00270e2ac0dc68e423d1868f5cac869d64d94702ee9e772ef5fd52b4612ead6f5a0003a1c3d496a186a1a72cfe3078e88168ff326473b8af785b254aa124c69064e400163d332d26ea2e7f66022bd963c4163a6f205d44e35ac83eea7d5a0f1236f09c0023f155555baa1083840831c538443e2805966ab97c8ec333435ac7ab58a979fe002f4b9c816d0c5dfc46b6b507028dd967ba0574f6f3f3503c8cfefca4bd88be7300007ccba7bd0cf11585241ba0e573ab5fbcc159220bfb4669de2cd3d11b9ac8a60020369d2d52fd9c8997c6bd384c3627b03da0cc0c2d2f5aa4b0c74a330192f4c2012278d29396e1c6bfaeb67626da24ec117429f4d207ddd2b0632cb09d12652ec10101e3a4ff8846e1655b007195e1b6d800b4c62a88173d4328002d39f673809954001031c5badf10560137006f3e24fa54b27298109f45802311f72682f8416daf870017f293c47a044b8950bb2432f13aabce8d2778e06acbc77b7ff5c0f9fcf19a0d01192e4f040dade991bfccb215e86d43f6d1dcfdba6b990901fc0803205971a8630100c8de7797ac2233659edad98015d4b09fd72795c88b7e72abe67332b6dfe419011b4b31bb8f4839e93470fdf6466cfeebb71e8268fc4eee7e1fc18c693db1b0ee010635360ad6bc1ac35171de94f599ff94b5b99bb8cbcb752c0d8bf814dcb17bf3011d0e8b621bb2d2ccf391b98afe47b113c135357f5704729a7424eb7d43d692ce0028c2ed7d17398ec2c7430b48d95e5b4641ba9aa09d938aee68a156aa708db4b7012db0d18235dbf4800a23edda7f53a433cb6a7df84a0b5cc4c1e810c4f0a2bd8201034aad9debd087e6b816ac31e8233d08ba685bde235a5f794f908405398c12ee0016d5d080eb4042680548d29f8730198051a9dccd0996d40c5a13b6949f14e4910025f28597f07d17439457e9e41a5c7f7daabbc134f6228be485f452461d5b996701220584b24e5a87af99109c460b2052df26f15e631ef8c36f18004ffd7a71a519002ae7670e81dc479985dd0caa0cb08f2128307b43aea07a6d3c5ab84aa648a5a70004ef828ddc623cb574e87065a5d7c3006597716c910190a866969dfea37c30d600249fb654c861c3688c2898fed0aac1fac075b6478146e3fb99d34ccaf790a21d0012a06b85562f201047ed922fe938e72069e4a25f0cc5782b1aec718c0bce46ea002e0dae8b0fe9e50fbe0ba74c6e0565212fddefef7053529cad2747978265f8a8011c140a7bc045eb496e520b4bd08e9dbdf18b9a1bbf6733be4248442d10a9fb0500302c870c17f7ef67e711df82b6603b30603694e188024fa41a14fada846d8ba9012db86e12e976195f38cba6915f7228c2e98fe0a266df942e7174e3f528ddb1d00102222e91f9a9e91904b17d64977352c93e5ac2f6e1d694041f7863ead356f5ee011f4e1eeef0606a9ae6d87562ed0f81dc0402d327102471c4b9dbb3fa3651ba09010e42adcbf49d9050d82ecaa5c40a9c9858aa0f97976cc593de7141d9aacc0a6c00200be9027f39b0dadb36df2114f3a7605a90347e3625304e290d83841365fa2a0011da530bc17fb6e3c5fcd5291fb286c9b52b943a1c93f68b7ac220ff9b008f170000000000000000000000000000000000000000000000000000000000000000000eab3f99967f03bb3a3b1e689145e406155d4c9e027a1206a1cc972f1003be5612eea86bea3b0ee07dafbc2610fe9c71bdeccead3ba0a2702f5da0d89d084f2c053f0931828d42aec32cd555d5d81639005192e5903da3c23218938c7c3dc918227a34fb4889a56ea461988da95aeca6e17dbf5865696fbe738bd7033f51f0b40346b290197557ac24db3e9281f0fedf01110dfeb4daf4d71163de652dc8b2b61778b5e0bd4f45541b35c62923b99b53c3b94f1478dd81708e14112e152e489e2c1c4c580d3e35a9f0693449a0af566deb3f32340373c023ffa6c9ff8d91f80d07af281574a4822870a05678b41d97c4a9b35541e6940f0120b9d47fc4bb2b2003e95bd2ec3c63245602f21808a875ba0d1028ca3e7869b6c6682a7125c1f2ff011ece8eb96ff3e0e9af0947749056b806e554fde39f475f0ca2211cf9198058a4002703f5443f1886e1caf60f775b6431bc948e4b0e2b76f56a8fc8c29da23caded041917938e845f826ddc5f2ec6aca0a985e6f6c98ea0cbc51f9429e2616500e20605af191eac7bd2696409d65dcbf3108079ec1f6bd5f9601b43dd3b58304d9d205b1ef7b34578d80236c0615ac79f69fcc7c92491bbbd3130cc22e8f0ea1fd21d2d5bfc8da06e2ba48acf70477d1cfefa7165a0804166027f0945faa85057cc236797a65ada0329e7de91712b4974fd83bb99ea97042788bfde4b8b9b5f1b251f6853fc4ffbdff382b24f209d4357099ea1c0d0c383dfd7f03d64bb7bff199406aae7f59190862d36ebefe8d011825bc663c6731f6397d5019f00055a3f80b71ab3b3813d5d509d89432a722ee789db88ca86c86fa76d6224b7eb3c5e66822b1e57f77674481d0a3a7252d47c4da5feab251db1b0b146620a9d271ca951c33f001080c18c31919d2de622fe0170824cc31ecaedd90d8214afcf47a7486474d65200153ade04144d5c29e2e0d6003fcf160bec90d79a42afcb4fe230bc695ce956ba001f4b437e4531531b85e326ccdf160e87408454ecd811fd41a51cc7a9585700df01092a076eebb6fb76ae2443dd7f007fe8edc4c7f54a1bdf48e8e5ae59ca513a9901205d75965eb434dd10e8425ff82d7f6695d4cf0b97507e800c3e3d59a60b83f3002d1496857827c872a53a792e86a74da252f12316972cfadbb2afcfa40a2883790108ccf31a2fdd88201361a0d4313a98a0272173132d1fa3d9bf018f35a7b439b701301da927ac71fea5a0024920ecbadd76f5f05f06b2d8e6874ae9a5348316585b002806c45af761489705e347dcc764ab531fbd7205c36c15f44ad1b633a609dda3000a40291cb5b71269ce0535a8b81ee3440e3db8208e4dd2af38c6591121c6a6560127f8dbc559ca73ecc28c0df0f38b7991bd348121cf5c111c4c505b019d5ef8de0018aae0f6ef38795ec5bac7e55ac5e580599a95043bc57ecc4930d2e1279269b2001c77bc717a5a1788e6157bf937e3f089ec9e27b0a7ab4eab11c25eec1918045300" } } ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": { "status": "OK", "string": "" } } ``` ## Submit Block Submit a mined block to the DERO network. #### Available parameters | Name | Type | Mandatory | Comment | |--------|---------|-----------|---------------| | jobid | string | true | Job ID | | mbl_blob | string | true | Mini Block Hashing Blob | #### Body #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10102/json_rpc \ -H 'content-type: application/json' \ -d '' ``` #### Result **To Do** ## Get Height Returns the current block height. #### Available parameters #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "DERO.GetHeight" } ``` #### **cURL Request** ```bash curl -X POST \ http://127.0.0.1:10102/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "DERO.GetHeight" }' ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": { "height": 36210, "stableheight": 36202, "topoheight": 36210, "status": "OK" } } ``` ## Get Block Count Returns the total number of blocks in the blockchain. #### Available parameters #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "DERO.GetBlockCount" } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10102/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "DERO.GetBlockCount" }' ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": { "count": 36215, "status": "OK" } } ``` ## Get Last Block Header Returns the header of the last block of the blockchain. #### Available parameters #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "DERO.GetLastBlockHeader" } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10102/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "DERO.GetLastBlockHeader" }' ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": { "block_header": { "depth": 0, "difficulty": "27629", "hash": "b8e540f25322e51492005c78f29f6809f601a9e6f4a89c87d10bd035a73e770b", "height": 36224, "topoheight": 36224, "major_version": 1, "minor_version": 1, "nonce": 0, "orphan_status": false, "syncblock": false, "sideblock": false, "txcount": 85, "reward": 0, "tips": [ "9633dad8e3cd7589959fcdf1c3dcaabe3a9e4da7bf64f929abc685c07e859874" ], "timestamp": 1643998300007 }, "status": "OK" } } ``` ## Get Block Template Return the Block Template to find a new block. #### Available parameters | Name | Type | Mandatory | Comment | |--------|---------|-----------|---------------| | wallet_address | string | true | DERO Address | | block | bool | false | Include Block | | miner | string | false | Miner in JobID | #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "DERO.GetBlockTemplate", "params": { "wallet_address": "deto1qyyhg0xznkaxt5udct6lnlylsexvwprun6jphv89xg008vq29jk4vqqayuknf", "block": true, "miner": "Slixe" } } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10102/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "DERO.GetBlockTemplate", "params": { "wallet_address": "deto1qyyhg0xznkaxt5udct6lnlylsexvwprun6jphv89xg008vq29jk4vqqayuknf", "block": true, "miner": "Slixe" } }' ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": { "jobid": "1643998645692.0.Slixe", "blocktemplate_blob": "0101000a93075a741d74bde710", "blockhashing_blob": "01010000017ec5f48dbc929b02010000021f9bcc1208dee302769931ad378a4c0c4b2c21b0cfb3e752607e12d2b6fa642500000000000000000000000000000000000000000000000000000000000000000001261d40140457b0cdbaf4b0d9c4a84d1a463e58dd640c1b9ce751735a0181528b09415d500000008d92261d4014000000001c705e03cba898cbab3683bf1f8cfd2400000000b0a397487357400b629e850241609a0000008d92261d401400000000cf01bc87c4a923fb34d51ac483aaf90b000000006e1499c694a04f7e197e55004161780000008d92261d401400000000eec07ce3efc1425bc0ad7e8c72d13b0500000000bad6dedbe2ac2958ed0c14004166180000008d92261d4014000000001c705e03cba898cbab3683bf1f8cfd240000000098b034fc16a4920b62bfb5034166a40000008d92261d401400000000fe9adfc28bacbdc815b3cd6b1e7fbc530000000026f43d2afb08c33e2579f700416fb50000008d92261d401400000000c3443540c243d11f706b6836d516a955000000002ed78a184271890c492571014171b90000008d92261d401400000000eec07ce3efc1425bc0ad7e8c72d13b05000000008f78534809752558ed2998004171970000008d92261d401400000000cf01bc87c4a923fb34d51ac483aaf90b0000000011c8b696eb90437e19bfa700417f550000008d92261d401400000000c3443540c243d11f706b6836d516a95500000000be142fad0edb0151395db60042a9f4782c542379ac7dfbca3fe99f80270cc4a2cdddbdcf173bffc7f026c567c2ed5583e12e08a9abdb358a28a3499fbab49b024914066f4d29d82b311195d3e42a7277cdcc6a7f9e105c35efbbcc9099fd563f28d2ddf8b14add0a93945f521278673c1f38885654752e44097dfd25bfc9f1e337f4457dd0248cec74bc4ca4aeb2427df130fa8cce24150854dd9dffa3670d5e9fd57a90987c9e0db07e122c3e08ee12c4f82c10f37a6dfe0f69fcd4ff6e482526781b9dd7e4a35a7891072f8d62fd342778f3eabddb14eceede4e310ddac280a8b372484108ea8c8e1dc39986f36a7e28904ca5aae7416a0d33e94e9a93a10220e1d79730f15689f83d8bfcdd16298c5e340d36cf27a18e6446fbda3ebe6b7889786d1ebca318f3b7f51244ed7b097d55e6b283dc8ddc3fb073bbd4fc6a84e599667674abb01cdd0d5b8474dc2f8be7ecef537cdb9e489557bdedaa2e7c48bebb663d82e79546a53d61f768a54eb7ef7bacd8d154672677067b069de1c0af7b5ac537b22d25fc3be164d4934b90e6bbcb9e75b2999392def043662e54125055fcbc03477dfa56bea59626fc513e75eadc492f817a104e94b1f14501941063ca4583f9ed6224302a5930fac34b9659a780fafa9af0cc7a6b9626c7b63d75c76c14b074ed8128172f8ca81f106dd909820b9b3b6ca5258420a71a11410e753950fd89b229574db162eecc92ab5b195827c059bfbf21c7c40be92c915cf733c90c5dee3001669e73c729e2d85bcd4245797152e427b1b265c2edc82d76db40559c77b69a9da2152ef4d0d8eefff4550c3350211057c2f9b5d49d9c8cf0ca9366b0c2e5dec651c49a8ac0fd01b21bcef566ceb5838ef5f0875c01414563a52de084d6d90e20da8f7b7dd5db65b7008ac385b150e6a371c34d8085a5b24d0b101b9965b35fa66ac082e926fcaa0088e830b9b66f941c6593d20226bda3f306dce0df36b6a52c8d831dcb343ccd4a92454d27949ae59cb9108d6d563f20f101744c62e24cc903f2eec88a4dea446e49288c05e139cd163a8918e6619e15aa2578660a220ca2d3ce0d3f93cfc929795fc63d93f66e26b6777898a619f18ce6d62df8bb1fe060dcf3fe5fa953543c254162efa7eb35b7a572646ecc2cc23a97d75e7def28a2542d8bd237b19d104733013ded66ba85e9a1c296628d56dc73fbc7d6159161ef0418d37280eb5f8de5002ab5eb767810a950de6e0fcb65e567db21fc7e208b7a8f8789b848642ec35691c98657c5b6c33f7b05e3937b74f312a52f20901674d215e73bedb53a859eb4e8910f35a47b2375ec4210d5b52d7ace224ab20b8e3551f040b11d016c2b6a4734d44c1023079a8196d5d57bae4a03e03e920fe1649dbb01e671f4a01beb85e90a4b4347cd843b31c5e18052b381d70a71c6fd0fb664a78056a3ae92be19373bf11124f799cb29fcb6f5c4c2db63bc169ac5f0852d3dff667615c47cfc278b2153026c9c4c10f6f3ed5ff6ad575206d1c2f5806788619f8577516bd5d6e8ed58f47fdc135a5d6196729eec1bcdb597c27727c17562baa6d35aa5b898fa4e63d8b2aa5bef53bfed13fe05c707eda80b7e4833728fa0348508959adf0c5d55c1334e1f77bffda45238ef5858a65994c06fc8243ae37e49d5ca103e5c3894963c9ffa189764929162edff317d6d591966aee7f24e1fa196e50078003882a608cdf7dc8948e3a20513bda589574bd9ccb68100ade9af11e37871b938361fafd3dd9a8d2d6c8d233d94ca2f1b838e14618d7289addf834543687d61766a7ac20f164268301875ef7b048e4b0ddf8ad349c83cc42bc620f0c4b45faa484609aeb56e82f811354df0ad17a485c3e4afe2d908743fa15939ebb7dc293bb7b3a37266f8c7277e4279ab45771df087e5af389a65929718637cac2c55720753fa7f4162f0e23f389d90932c20172e4012d87e818e35a3b46f6956be6210b501bfa3a658656af9aec6033436b752a17a8606e6f101978167308f1969aa98e107d64a3598fef0edbc8a24733e40716d025dd31ba8d15dbf2321741e4962ff4b327bb355cec55e762023d08847e6a10004f3212d98ddbede12485a894f7c8802bbc94d5073f737d25d078af7880053ead4a5eb2c7989c46eb122345f4e6d9fef3f405fb5da4998d8f04aea21d568f3b72203e1f7f1e9e09ccc8fe22ea7c31614929422ddd45e09e59f65adfc6fcf8b137d65afb965cf23db5fb23614ae6656bf6959e2dcdbcea6f6976701ae86db4ae15933c645c39c5186d9937d207e224aeffe1e43cdebc01c23b917afd1a8669399e965157e59ff0c4417a9fee42737e3bbbdbb3714d9a057b315103f55dce2fc92973c9a9c60403d92b534f65532672a7363f116623ef60425cf12959ca9209b4c065c2c4e30e21d30eb116734f10d3d1a630dacafe264804b5d500109e14c79beab1f13db202b7db79c96d0127fa1b7540219b682534bd55d7eae6e799bbaaba07df7ecfa4c9e8142e45b3973174185aba6ed8c7ef81b650430ab066a44715c3609cda984e389e78d26bc2170ad0a4c6d41478665739a720c28ed742b571dfb8adc8bdb9a3e31c977afbe0582be9eee24a27cc9d7ec467a81d9a954cbe77b1fe515581b0909a8e26b7e311dea1e3c75edf275bf0472a94c8d8a4160dd1a7923c6ed895c6ec7723c146079fbe11857cecacd7ec5d18523399bb1653688f8473d0eb6bd4caf9609f070a1d7beb571257c16d68c8ff0ef56b49e87dfaa8fe49f04dc9b71c7ded23534ea9f127ae5022f863e2ea12b7e79988464fe3b9db79d2d96808be48d457704eb9bcb395790d157673f979fefc1b45f665607a6c0ebb361818e6c944a6e387f9dea4d3787ba07f1cc7c7777c0f67c0eb41d3f1b8f10860a654831d2c7367a50c50bebf1bd52f1b663e0e0ad8e251440c7a31f912a3680dbb75af7337ba99f01d0960093d0b650a6675a93075a741d74bde710", "difficulty": "20614", "difficultyuint64": 20614, "height": 36242, "prev_hash": "261d40140457b0cdbaf4b0d9c4a84d1a463e58dd640c1b9ce751735a0181528b", "epochmilli": 0, "blocks": 0, "miniblocks": 0, "lasterror": "", "status": "OK" } } ``` ## Get Encrypted Balance Returns the balance of the selected asset from a valid DERO address. #### Available parameters | Name | Type | Mandatory | Comment | |--------|---------|-----------|---------------| | address | string | true | DERO Address | | topoheight | int64 | true | balance at specified height | | scid | Hash | false | SCID of asset/token | | treehash | string | false | Merkle Balance Tree Hash | #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "DERO.GetEncryptedBalance", "params": { "address": "deto1qyyhg0xznkaxt5udct6lnlylsexvwprun6jphv89xg008vq29jk4vqqayuknf", "topoheight": -1 } } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10102/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "DERO.GetEncryptedBalance", "params": { "address": "deto1qyyhg0xznkaxt5udct6lnlylsexvwprun6jphv89xg008vq29jk4vqqayuknf", "topoheight": -1 } }' ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": { "scid": "0000000000000000000000000000000000000000000000000000000000000000", "data": "aff7011376c6b7c6682d2410e5cab55b075221818f815743969c94cd9c7e2a2ff28b8e002db1812376e8846b66aa56f9e2d2ec0230e7b658efba875bd877dd43ac197c6801", "registration": 31281, "bits": 20, "height": 36261, "topoheight": 36261, "blockhash": "987ad08aa23ad24a32862d085c451369e7b1b21e478369ea63aa9e4e0b81050f", "treehash": "a823f22d9d50e55bc1d1372be0e9287ebc2eb6bbeb4d0ec86f83a2b8a3c394b8", "dheight": 36261, "dtopoheight": 36261, "dtreehash": "a823f22d9d50e55bc1d1372be0e9287ebc2eb6bbeb4d0ec86f83a2b8a3c394b8", "status": "OK" } } ``` *Note: The value of topoheight is set to -1 in the request to retrieve from the last block directly.* ## Get Smart Contract Returns information related to a Smart Contract. #### Available parameters | Name | Type | Mandatory | Comment | |--------|---------|-----------|---------------| | scid | Hash | true | Smart Contract ID | | code | bool | false | Returns code or not | | variables | bool | false | Returns all variables or not | | topoheight | int64 | false | data at specified height | | keysuint64 | []uint64 | false | All variables with these int keys | | keysstring | []string | false | All variables with these string keys | | keysbytes | [][]byte | false | All variables with these bytes keys | #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "DERO.GetSC", "params": { "scid": "0000000000000000000000000000000000000000000000000000000000000001", "code": true, "variables": true } } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10102/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "DERO.GetSC", "params": { "scid": "0000000000000000000000000000000000000000000000000000000000000001", "code": true, "variables": true } }' ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": { "stringkeys": { "C": "2f2a204e616d65205365727669636520534d41525420434f4e545241435420696e2044564d2d42415349432e20200a202020416c6c6f77732061207573657220746f207265676973746572206e616d657320776869636820636f756c64206265206c6f6f6b65642062792077616c6c65747320666f72206561737920746f20757365206e616d65207768696c65207472616e736665720a2a2f0a0a0a202f2f20546869732066756e6374696f6e206973207573656420746f20696e697469616c697a6520706172616d657465727320647572696e6720696e7374616c6c2074696d650a0946756e6374696f6e20496e697469616c697a6528292055696e7436340a093130202052455455524e2030200a09456e642046756e6374696f6e200a0a202020202f2f2052656769737465722061206e616d652c206c696d6974206e616d6573206f662035206f72206c657373206c656e6774680a2020202046756e6374696f6e205265676973746572286e616d6520537472696e67292055696e743634200a0931302020494620455849535453286e616d6529205448454e20474f544f2035302020202f2f206966206e616d6520697320616c726561647920757365642c2069742063616e6e6f74207265726567697374657265640a09313520204946205354524c454e286e616d6529203e3d203634205448454e20474f544f203530202f2f20736b6970206e616d6573206d69737573650a09323020204946205354524c454e286e616d6529203e3d2036205448454e20474f544f203430200a09333020204946205349474e45522829203d3d20616464726573735f72617728226465746f317179767965797a72636d32667a66366b79713765676b6573327566676e7935786e3737793674797068667839733777336d767964357171796e723568782229205448454e20474f544f2034300a09333520204946205349474e4552282920213d20616464726573735f72617728226465746f3171793065686e716a7072307778716e6b6e79633636647532667378796b7470706b72386d3865366a76706c703935346k6c666a7a327171647a636438702229205448454e20474f544f203530200a093430202053544f5245286e616d652c5349474e45522829290a093530202052455455524e20300a09456e642046756e6374696f6e0a0a2020090a092f2f20546869732066756e6374696f6e206973207573656420746f206368616e6765206f776e6572200a092f2f206f776e657220697320616e20737472696e6720666f726d206f662061646472657373200a0946756e6374696f6e205472616e736665724f776e657273686970286e616d6520537472696e672c6e65776f776e657220537472696e67292055696e743634200a09313020204946204c4f4144286e616d652920213d205349474e45522829205448454e20474f544f203330200a093230202053544f5245286e616d652c414444524553535f524157286e65776f776e657229290a093330202052455455524e20300a09456e642046756e6374696f6e0a090a", "captain": "07169e14f6a6efb41522a0a0503ef59bf221ef89072903998cc7b599ad5351d801" }, "balances": { "0000000000000000000000000000000000000000000000000000000000000000": 0 }, "balance": 0, "code": "/* Name Service SMART CONTRACT in DVM-BASIC. \n Allows a user to register names which could be looked by wallets for easy to use name while transfer\n*/\n\n\n // This function is used to initialize parameters during install time\n\tFunction Initialize() Uint64\n\t10 RETURN 0 \n\tEnd Function \n\n // Register a name, limit names of 5 or less length\n Function Register(name String) Uint64 \n\t10 IF EXISTS(name) THEN GOTO 50 // if name is already used, it cannot reregistered\n\t15 IF STRLEN(name) >= 64 THEN GOTO 50 // skip names misuse\n\t20 IF STRLEN(name) >= 6 THEN GOTO 40 \n\t30 IF SIGNER() == address_raw(\"deto1qyvyeyzrcm2fzf6kyq7egkes2ufgny5xn77y6typhfx9s7w3mvyd5qqynr5hx\") THEN GOTO 40\n\t35 IF SIGNER() != address_raw(\"deto1qy0ehnqjpr0wxqnknyc66du2fsxyktppkr8m8e6jvplp954klfjz2qqdzcd8p\") THEN GOTO 50 \n\t40 STORE(name,SIGNER())\n\t50 RETURN 0\n\tEnd Function\n\n \t\n\t// This function is used to change owner \n\t// owner is an string form of address \n\tFunction TransferOwnership(name String,newowner String) Uint64 \n\t10 IF LOAD(name) != SIGNER() THEN GOTO 30 \n\t20 STORE(name,ADDRESS_RAW(newowner))\n\t30 RETURN 0\n\tEnd Function\n\t\n", "status": "OK" } } ``` ## Get Gas Estimate Returns the total costs (= storage and compute) to be paid for a call on a function of a Smart Contract. #### Available parameters | Name | Type | Mandatory | Comment | |--------|---------|-----------|---------------| | transfers | []Transfer | false | All transfers | | sc | string | false | SC Code to deploy | | sc_rpc | Arguments | false | SC Call arguments | | signer | string | false | Signer for SC call | #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "DERO.GetGasEstimate", "params": { "transfers": [], "sc_rpc": [{ "name": "SC_ACTION", "datatype": "U", "value": 0 }, { "name": "SC_ID", "datatype": "H", "value": "0000000000000000000000000000000000000000000000000000000000000001" }, { "name": "entrypoint", "datatype": "S", "value": "Register" }, { "name": "name", "datatype": "S", "value": "Slixe" } ], "signer": "deto1qyyhg0xznkaxt5udct6lnlylsexvwprun6jphv89xg008vq29jk4vqqayuknf" } } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10102/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "DERO.GetGasEstimate", "params": { "transfers": [], "sc_rpc": [{ "name": "SC_ACTION", "datatype": "U", "value": 0 }, { "name": "SC_ID", "datatype": "H", "value": "0000000000000000000000000000000000000000000000000000000000000001" }, { "name": "entrypoint", "datatype": "S", "value": "Register" }, { "name": "name", "datatype": "S", "value": "Slixe" } ], "signer": "deto1qyyhg0xznkaxt5udct6lnlylsexvwprun6jphv89xg008vq29jk4vqqayuknf" } }' ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": { "gascompute": 208200, "gasstorage": 88, "status": "OK" } } ``` ## Name To Address Returns the DERO address associated with the registered name. #### Available parameters | Name | Type | Mandatory | Comment | |--------|---------|-----------|---------------| | name | string | true | Name for look up | | topoheight | int64 | true | lookup in reference to this topo height | #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "DERO.NameToAddress", "params": { "name": "captain", "topoheight": -1 } } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10102/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "DERO.NameToAddress", "params": { "name": "captain", "topoheight": -1 } }' ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": { "name": "captain", "address": "deto1qyr3d8s576nwldq4y2s2q5p77kdlyg003yrjjque3nrmtxdd2dgasqgm94m7v", "status": "OK" } } ``` --- ## Related Pages **Getting Started:** - [Running a Node](/basics/running-a-node.md) - Setup your own DERO node - [DERO Daemon](/basics/daemon.md) - Understanding the daemon **Related APIs:** - [Wallet RPC API](/rpc-api/wallet-rpc-api.md) - Wallet RPC methods - [Smart Contracts](/smartContracts/token.md) - Deploy and interact with contracts **Network & Mining:** - [DERO Mining](/basics/mining.md) - Get block templates for mining - [Encrypted Network](/features/encrypted-network.md) - P2P network details **For Developers:** - [DVM-BASIC Guide](/dvm/dvm-basic.md) - Build smart contracts - [DERO Tokens](/basics/tokens.md) - Understanding assets and balances --- --- title: "DERO Wallet RPC API: Developer Integration Guide | DERO Blockchain" description: "Complete reference for DERO wallet RPC API methods with examples for balance management, transaction creation, and address operations in applications." keywords: ["DERO wallet API", "cryptocurrency wallet integration", "blockchain wallet API", "DERO integration", "wallet RPC endpoints", "cryptocurrency transactions", "wallet development", "DERO payments", "crypto API", "wallet automation"] date: "2024-08-26" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/wallet-api.jpeg" slug: "wallet-rpc-api" canonicalUrl: "https://derod.org/rpc-api/wallet-rpc-api" tags: ["rpc", "api", "wallet", "integration", "development", "payments", "reference"] --- # DERO Wallet RPC API A wallet RPC (Remote Procedure Call) enables programmatic control of a DERO wallet. This API allows payment processors, exchanges, and applications to automate wallet operations. **Source:** `rpc/wallet_rpc.go` - All RPC methods verified against Release 142 ## Network Ports | Network | Wallet RPC Port | Usage | |---------|-----------------|-------| | **Mainnet** | `10103` | Production use | | **Testnet** | `40403` | Development/testing | **Source:** `config/config.go:104,124` ## Enable RPC Server The RPC server is **not enabled by default**. Start the wallet with `--rpc-server` to enable it: ```bash # Mainnet ./dero-wallet-cli --rpc-server --rpc-bind=127.0.0.1:10103 # With authentication ./dero-wallet-cli --rpc-server --rpc-login=username:password ``` ## What You Can Do - **Manage balances** - Query DERO and asset balances - **Send transactions** - Transfer DERO and assets with privacy - **Receive payments** - Generate integrated addresses, monitor transfers - **Smart contract interaction** - Call SC methods, query state - **Address management** - Get wallet address, generate integrated addresses ## Echo Test endpoint to verify that the RPC server is enabled and working well on the wallet side. #### Available parameters | Name | Type | Mandatory | Comment | |------|-----------|-----------|--------------------------| | | []string | true | Array of string | #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "Echo", "params": ["Hello", "World", "!"] } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10103/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "Echo", "params": ["Hello", "World", "!"] }' ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": "WALLET Hello World !" } ``` ## Get Address Returns the DERO address of the wallet to receive DEROs or other tokens. #### Available parameters No parameters #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "GetAddress" } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10103/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "GetAddress" }' ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": { "address": "deto1qyyhg0xznkaxt5udct6lnlylsexvwprun6jphv89xg008vq29jk4vqqayuknf" } } ``` ## Get Balance Retrieves the current balance of the wallet. #### Available parameters No parameters #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "GetBalance" } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10103/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "GetBalance" }' ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": { "balance": 800000, "unlocked_balance": 800000 } } ``` **NOTE:** The amount is in atomic format. As a reminder, 10^5 (=100000) is equivalent to 1 DERO. When using a transfer to carry a payload (a comment, destination port, or app data) rather than to send value, the amount must still be at least **1 atomic unit** (`0.00001 DERO`): a zero-amount transfer creates no output for the recipient's wallet to detect, so its attached `payload_rpc` never reaches them even though the transaction is valid and mined. This applies to any use of a transfer as a data carrier, not just payments. If this address is not registered on the blockchain, you will get this error: ```json { "jsonrpc": "2.0", "id": "1", "error": { "code": -32098, "message": "Account Unregistered" } } ``` ## Get Height Returns at which block height the wallet is synchronized. #### Available parameters No parameters #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "GetHeight" } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10103/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "GetHeight" }' ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": { "height": 420 } } ``` ## Get Transfer by TXID Returns the details of the transaction based on its hash. #### Available parameters | Name | Type | Mandatory | |------|-----------|-----------| | hash | Hash | true | #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "GetTransferbyTXID", "params": { "txid": "2a74bcc6262f48630967129793f3b87dc30236f2cb5df6ebb09d620ec0cb503a" } } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10103/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "GetTransferbyTXID", "params": { "txid": "2a74bcc6262f48630967129793f3b87dc30236f2cb5df6ebb09d620ec0cb503a" } }' ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": { "entry": { "height": 31297, "topoheight": 31297, "blockhash": "44e010e6ae56e66e75b158871570233a8a8b918491efc2d02ce793a7ce258612", "minerreward": 0, "tpos": 17, "pos": 0, "coinbase": false, "incoming": true, "txid": "2a74bcc6262f48630967129793f3b87dc30236f2cb5df6ebb09d620ec0cb503a", "destination": "", "amount": 500000, "fees": 451, "proof": "deroproof1qy3zfvkwdz87xa7mvxc0qq7nsmcgkl3gsf00a2amhk7fs2yu09r4uqdzvfyyskpqckdxyd8vgtzd75mjujsyzj6swrfdy6gw7alx78ak23v6ql60ewqxy4j4rgqq0gfqsjjq9u", "status": 0, "time": "2022-02-03T17:51:16.006+01:00", "ewdata": "2efc785f92e9ffdaf1935186e0ffe561e500632722c73f95e741136389a347b8002642ae3d734c6b119a28884920036e895fc8e6a33f9c4ec6d90da1a4d1b65ef901", "data": "AqFoQ29tbWVudFNySGVsbG8gZnJvbSBTbGl4ZSAhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", "payloadtype": 0, "payload": "oWhDb21tZW50U3JIZWxsbyBmcm9tIFNsaXhlICEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "payload_rpc": [ { "name": "Comment", "datatype": "S", "value": "Hello from Slixe !" } ], "sender": "deto1qyj4kx6azntn9psmg7dsfkuv9qs9xde0s94nmmhm2a0damffpm2zzqqcudacc", "dstport": 0, "srcport": 0 } } } ``` ## Get Transfers Returns all transactions present in the portfolio against the applied filters. #### Available parameters | Name | Type | Mandatory | Comment | |--------|---------|-----------|---------------| | scid | Hash | false | Smart Contract ID | | coinbase | bool | false | Accept coinbase TX ? | | in | bool | false | Accept incoming TX ? | | out | bool | false | Accept outgoing TX ? | | min_height | uint64 | false | Minimum height | | max_height | uint64 | false | Maximum height | | sender | string | false | Sender address equal | | receiver | string | false | Receiver address equal | | dstport | uint64 | false | Destination Port (Service) | | srcport | uint64 | false | Source Port (Service) | #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "GetTransfers", "params": { "out": true, "in": true } } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10103/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "GetTransfers", "params": { "out": true, "in": true } }' ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": { "entries": [ { "height": 31297, "topoheight": 31297, "blockhash": "44e010e6ae56e66e75b158871570233a8a8b918491efc2d02ce793a7ce258612", "minerreward": 0, "tpos": 17, "pos": 0, "coinbase": false, "incoming": true, "txid": "2a74bcc6262f48630967129793f3b87dc30236f2cb5df6ebb09d620ec0cb503a", "destination": "", "amount": 500000, "fees": 451, "proof": "deroproof1qy3zfvkwdz87xa7mvxc0qq7nsmcgkl3gsf00a2amhk7fs2yu09r4uqdzvfyyskpqckdxyd8vgtzd75mjujsyzj6swrfdy6gw7alx78ak23v6ql60ewqxy4j4rgqq0gfqsjjq9u", "status": 0, "time": "2022-02-03T17:51:16.006+01:00", "ewdata": "2efc785f92e9ffdaf1935186e0ffe561e500632722c73f95e741136389a347b8002642ae3d734c6b119a28884920036e895fc8e6a33f9c4ec6d90da1a4d1b65ef901", "data": "AqFoQ29tbWVudFNySGVsbG8gZnJvbSBTbGl4ZSAhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==", "payloadtype": 0, "payload": "oWhDb21tZW50U3JIZWxsbyBmcm9tIFNsaXhlICEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", "payload_rpc": [ { "name": "Comment", "datatype": "S", "value": "Hello from Slixe !" } ], "sender": "deto1qyj4kx6azntn9psmg7dsfkuv9qs9xde0s94nmmhm2a0damffpm2zzqqcudacc", "dstport": 0, "srcport": 0 } ] } } ``` ## Make Integrated Address Returns a new integrated address with Payloads included. #### Available parameters | Name | Type | Mandatory | Comment | |--------|---------|-----------|---------------| | address | string | false | DERO Address (if empty, the one from wallet is used) | | payload_rpc | Argument | false | Parameters to include in address | #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "MakeIntegratedAddress", "params": { "payload_rpc": [ { "name": "Comment", "datatype": "S", "value": "Hello from integrated address !" } ] } } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10103/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "MakeIntegratedAddress", "params": { "payload_rpc": [ { "name": "Comment", "datatype": "S", "value": "Hello from integrated address !" } ] } }' ``` #### **Result** ```json { "jsonrpc": "2.0", "id": "1", "result": { "integrated_address": "detoi1qyyhg0xznkaxt5udct6lnlylsexvwprun6jphv89xg008vq29jk4vq9pdppk7mtdv4h8g5mcrayx2mrvdusxvun0d5sxjmn5v4nhyct5v4jzqctyv3ex2umnyqssvnqraw", "payload_rpc": [ { "name": "Comment", "datatype": "S", "value": "Hello from integrated address !" } ] } } ``` ## Split Integrated Address Returns the DERO address and the payloads included in an Integrated Address. #### Available parameters | Name | Type | Mandatory | Comment | |--------|---------|-----------|---------------| | integrated_address | string | true | Integrated Address to decode | #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "SplitIntegratedAddress", "params": { "integrated_address": "detoi1qyyhg0xznkaxt5udct6lnlylsexvwprun6jphv89xg008vq29jk4vq9pdppk7mtdv4h8g5mcrayx2mrvdusxvun0d5sxjmn5v4nhyct5v4jzqctyv3ex2umnyqssvnqraw" } } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10103/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "SplitIntegratedAddress", "params": { "integrated_address": "detoi1qyyhg0xznkaxt5udct6lnlylsexvwprun6jphv89xg008vq29jk4vq9pdppk7mtdv4h8g5mcrayx2mrvdusxvun0d5sxjmn5v4nhyct5v4jzqctyv3ex2umnyqssvnqraw" } }' ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": { "address": "deto1qyyhg0xznkaxt5udct6lnlylsexvwprun6jphv89xg008vq29jk4vqqayuknf", "payload_rpc": [ { "name": "Comment", "datatype": "S", "value": "Hello from integrated address !" } ] } } ``` ## Query Key Returns the mnemonic key (seed) associated with this portfolio. #### Available parameters | Name | Type | Mandatory | Comment | |--------|---------|-----------|---------------| | key_type | string | true | Key Type ("mnemonic" only) | #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "QueryKey", "params": { "key_type": "mnemonic" } } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10103/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "QueryKey", "params": { "key_type": "mnemonic" } }' ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": { "key": "eavesdrop sailor tavern fizzle mammal were utmost stellar rafts vats dedicated dosage lynx cent after toyed coexist zippers lipstick aztec dedicated custom chrome onto launching" } } ``` ## Transfer Creates a transaction and returns its hash. #### Available parameters | Name | Type | Mandatory | Comment | |--------|---------|-----------|---------------| | scid | Hash | false | SCID of asset | | destination | string | false | DERO Address of receiver | | amount | uint64 | false | Amount of token to send | | burn | uint64 | false | Amount of token to burn | | payload_rpc | Arguments | false | Payload Arguments | #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "transfer", "params": { "transfers": [{ "scid": "0000000000000000000000000000000000000000000000000000000000000000", "destination": "deto1qyj4kx6azntn9psmg7dsfkuv9qs9xde0s94nmmhm2a0damffpm2zzqqcudacc", "amount": 100000 }], "ringsize": 16 } } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10103/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "transfer", "params": { "transfers": [{ "scid": "0000000000000000000000000000000000000000000000000000000000000000", "destination": "deto1qyj4kx6azntn9psmg7dsfkuv9qs9xde0s94nmmhm2a0damffpm2zzqqcudacc", "amount": 100000 }], "ringsize": 16 } }' ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": { "txid": "5201c319d04fb72012ecb2fd8c903feff50bbd5db39c60dfee795b9b3a90433a" } } ``` ## Transfer 2 Creates a transaction to several distinct addresses and returns its hash. #### Available parameters | Name | Type | Mandatory | Comment | |--------|---------|-----------|---------------| | transfers | []Transfer | false | see previous request | | sc | string | false | SC Code to deploy | | sc_rpc | Arguments | false | SC Call Arguments | | ringsize | uint64 | false | Level of anonymity | | scid | string | false | SCID to call | | fees | uint64 | false | Tx Fees | | signer | string | false | used for gas estimation | #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "transfer", "params": { "transfers": [{ "destination": "deto1qyj4kx6azntn9psmg7dsfkuv9qs9xde0s94nmmhm2a0damffpm2zzqqcudacc", "amount": 100000 }, { "destination": "deto1qydvjhl67a3hmcw6zq9yt449extwshzcjxkd7lgk4uhgpyxdr494yqg6zwnc2", "amount": 100000 } ], "ringsize": 32 } } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10103/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "transfer", "params": { "transfers": [{ "destination": "deto1qyj4kx6azntn9psmg7dsfkuv9qs9xde0s94nmmhm2a0damffpm2zzqqcudacc", "amount": 100000 }, { "destination": "deto1qydvjhl67a3hmcw6zq9yt449extwshzcjxkd7lgk4uhgpyxdr494yqg6zwnc2", "amount": 100000 } ], "ringsize": 32 } }' ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": { "txid": "3a2712ae039e3f55b4cee132ec7ab76b912d05b3c1fc2744ae2ddd2c18be893e" } } ``` ## Smart Contract Invoke Creates a transaction to call a Smart Contract function and returns its hash. #### Available parameters | Name | Type | Mandatory | Comment | |--------|---------|-----------|---------------| | scid | string | true | SCID of asset/token | | sc_rpc | Arguments | true | SC Arguments | | sc_dero_deposit | uint64 | false | Amount of DERO to deposit | | sc_token_deposit | uint64 | false | Amount of token to deposit | | ringsize | uint64 | false | Level of anonymity | #### Body ```json { "jsonrpc": "2.0", "id": "1", "method": "scinvoke", "params": { "scid": "0000000000000000000000000000000000000000000000000000000000000001", "ringsize": 2, "sc_rpc": [ { "name": "entrypoint", "datatype": "S", "value": "Register" }, { "name": "name", "datatype": "S", "value": "Slixe" } ] } } ``` #### cURL Request ```bash curl -X POST \ http://127.0.0.1:10103/json_rpc \ -H 'content-type: application/json' \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "scinvoke", "params": { "scid": "0000000000000000000000000000000000000000000000000000000000000001", "ringsize": 2, "sc_rpc": [ { "name": "entrypoint", "datatype": "S", "value": "Register" }, { "name": "name", "datatype": "S", "value": "Slixe" } ] } }' ``` #### Result ```json { "jsonrpc": "2.0", "id": "1", "result": { "txid": "bf4b2cd942f4394a03d0d66bbf8c0639f5cbcbf340becc39d4c9e02f987cecca" } } ``` --- ## Related Pages **Getting Started:** - [DERO Wallets](/basics/wallets.md) - Wallet options overview - [Running a Node](/basics/running-a-node.md) - Setup wallet RPC server **Related APIs:** - [Daemon RPC API](/rpc-api/daemon-rpc-api.md) - Node RPC methods - [Smart Contract Examples](/smartContracts/token.md) - Deploy contracts via RPC **Understanding Privacy:** - [Transaction Privacy](/privacy/transaction-privacy.md) - How transfers stay private - [Homomorphic Encryption](/privacy/homomorphic-encryption.md) - Encrypted balances - [Payload Proofs](/privacy/payload-proofs.md) - Prove transfers cryptographically **For Developers:** - [DVM-BASIC Guide](/dvm/dvm-basic.md) - Smart contract language - [DERO Tokens](/basics/tokens.md) - Send and receive assets --- --- title: "DERO Assets Exchange: Token Swap Smart Contract | DERO Blockchain" description: "Guide to creating and using DERO's asset interchange smart contracts for secure token swaps, with step-by-step instructions for deployment and token exchange." keywords: ["DERO asset exchange", "token swap", "smart contract exchange", "cryptocurrency exchange", "DVM-BASIC", "blockchain trading", "token interchange", "DERO tokens", "decentralized exchange", "private token exchange"] date: "2024-08-26" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/asset-exchange.jpeg" slug: "assets" canonicalUrl: "https://derod.org/smartContracts/assets" tags: ["smart-contracts", "assets", "exchange", "DVM-BASIC", "DEX"] --- # Assets Interchange Smart Contract **Testnet Tutorial:** This guide uses testnet ports (40402/40403). Always test smart contracts on testnet before deploying to mainnet. For mainnet, use ports **10102** (daemon) and **10103** (wallet). This Smart Contract converts assetOne to assetTwo as per the defined ratio in the contract, provided the exchange has sufficient asset balances. ### Steps to Create an Exchange Contract: 1. **Create the first token** and deposit it into the exchange: - [Link to token example 1](https://github.com/deroproject/documentation/tree/master/DVMDOCS/examples/token) ```bash curl --request POST --data-binary @token.bas http://127.0.0.1:40403/install_sc ``` 2. **Create the second token** and deposit it into the exchange: - [Link to token example 2](https://github.com/deroproject/documentation/tree/master/DVMDOCS/examples/token) ```bash curl --request POST --data-binary @token2.bas http://127.0.0.1:40403/install_sc ``` 3. **Create and install** the [Asset Exchange Smart Contract](https://github.com/deroproject/documentation/blob/master/DVMDOCS/examples/assetexchange/asset_exchange.bas): ```bash curl --request POST --data-binary @asset_exchange.bas http://127.0.0.1:40403/install_sc ``` 4. **Deposit assetOne/token1** to the exchange contract: ```bash curl --silent http://127.0.0.1:40403/json_rpc -d '{ "jsonrpc":"2.0", "id":"0", "method":"transfer", "params":{ "scid":"Interchange-SCID", "ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"Deposit"}], "transfers": [ {"scid":"ASSET_ONE_SCID", "burn":AssetOneCount_DEPOSITED_TO_EXCHANGE} ] } }' -H 'Content-Type: application/json' ``` 5. **Swap assetOne for assetTwo** via the exchange contract: ```bash curl --silent http://127.0.0.1:40403/json_rpc -d '{ "jsonrpc":"2.0", "id":"0", "method":"transfer", "params":{ "scid":"Interchange-SCID", "ringsize":2, "sc_rpc":[ {"name":"entrypoint","datatype":"S","value":"Interchange"}, {"name":"incoming","datatype":"H","value":"ASSET_ONE_SCID"}, {"name":"outgoing","datatype":"H","value":"ASSET_TWO_SCID"} ], "transfers": [ {"scid":"ASSET_ONE_SCID", "burn":AssetOneCount_TO_BE__Converted} ] } }' -H 'Content-Type: application/json' ``` 6. **Check the balance of assetTwo** in the wallet: ```bash balance ASSET_TWO_SCID ``` **Note:** The variables used above need to be changed accordingly. SCIDs are transaction IDs returned by the respective commands. Replace variables: - `Interchange-SCID` - `ASSET_ONE_SCID` - `ASSET_TWO_SCID` - `AssetOneCount_DEPOSITED_TO_EXCHANGE` - `AssetTwoCount_DEPOSITED_TO_EXCHANGE` - `AssetOneCount_TO_BE__Converted` DERO Smart Contracts Tokens privacy can be understood just like banks handle cash. Once cash is out from the bank, the bank is not aware of it (who owns what value) until it is deposited back. The smart contract only maintains supply and other necessary items to keep it working. DERO Tokens can be transferred to other wallets just like native DERO with Homomorphic Encryption and without involvement of issuing Smart Contracts. Token issuing Smart Contract cannot hold/freeze/control their tokens once they are issued and sent to any wallet. This token is Private. Use `Function InitializePrivate() Uint64` to make any Smart Contract private. ## asset.bas **Private Token Smart Contract Example in DVM-BASIC.** ```basic /* Private Token Smart Contract Example in DVM-BASIC. */ // Issue Asset after depositing DERO (Convert DERO to TOKENX) Function IssueAsset() Uint64 10 SEND_ASSET_TO_ADDRESS(SIGNER(), DEROVALUE(),SCID()) // send asset without knowing original balance, this is done homomorphically 20 RETURN 0 End Function // This function is used to initialize parameters during install time // InitializePrivate initializes a private SC Function InitializePrivate() Uint64 40 RETURN 0 End Function ``` ## asset_exchange.bas **Asset Interchange/Exchange Smart Contract Example in DVM-BASIC.** ```basic // Asset Interchange/Exchnage Smart Contract Example in DVM-BASIC. // This SC allows you to deposit an arbitrary token, into it // and later allows you to swap one token with another // if the smart contract has enough balance to cover outgoing transfer it will be done // deposits an arbitrary token // owner should deposits all arbitrary types Function Deposit() Uint64 20 RETURN 0 End Function // incoming represents incoming asset type basicallly an SCID // outgoing represents outgoing asset type basicallly an SCID Function Interchange(incoming String, outgoing String) Uint64 10 SEND_ASSET_TO_ADDRESS(SIGNER(), ASSETVALUE(incoming) / 2, outgoing) // 1:1/2 interchange of assets 20 RETURN 0 End Function Function Initialize() Uint64 10 STORE("owner", SIGNER()) // store in DB ["owner"] = address 40 RETURN 0 End Function // everything below this is supplementary and not required // This function is used to change owner // owner is an string form of address Function TransferOwnership(newowner String) Uint64 10 IF LOAD("owner") == SIGNER() THEN GOTO 30 20 RETURN 1 30 STORE("tmpowner", ADDRESS_RAW(newowner)) 40 RETURN 0 End Function // Until the new owner claims ownership, existing owner remains owner Function ClaimOwnership() Uint64 10 IF LOAD("tmpowner") == SIGNER() THEN GOTO 30 20 RETURN 1 30 STORE("owner", SIGNER()) // ownership claim successful 40 RETURN 0 End Function // if signer is owner, withdraw any requested funds // if everthing is okay, they will be showing in signer's wallet Function Withdraw(amount Uint64, asset String) Uint64 10 IF LOAD("owner") == SIGNER() THEN GOTO 30 20 RETURN 1 30 SEND_ASSET_TO_ADDRESS(SIGNER(), amount, asset) 40 RETURN 0 End Function // if signer is owner, provide him rights to update code anytime // make sure update is always available to SC Function UpdateCode(code String) Uint64 10 IF LOAD("owner") == SIGNER() THEN GOTO 30 20 RETURN 1 30 UPDATE_SC_CODE(code) 40 RETURN 0 End Function ``` --- ## Related Pages **Understand Token Privacy:** - [DERO Tokens Overview](/basics/tokens.md) - How private tokens work - [Homomorphic Encryption](/privacy/homomorphic-encryption.md) - Encrypted balances explained - [Private Smart Contracts](/privacy/private-smart-contracts.md) - Privacy features **Learn the Language:** - [DVM-BASIC Programming Guide](/dvm/dvm-basic.md) - Smart contract syntax - [DERO Virtual Machine](/dvm/dero-virtual-machine.md) - VM architecture **More Examples:** - [Token Contract](/smartContracts/token.md) - Basic private token - [Lottery Contract](/smartContracts/lottery.md) - Randomized winner selection - [Name Service](/smartContracts/name.md) - Username registration **Deploy:** - [Wallet RPC API](/rpc-api/wallet-rpc-api.md) - Install and interact with contracts --- --- title: "DERO Lottery Smart Contract: Decentralized Gaming | DERO Blockchain" description: "Complete guide to implementing a blockchain-based lottery system on DERO with smart contracts, including deployment, testing, and winner selection logic." keywords: ["DERO lottery", "blockchain lottery", "smart contract game", "decentralized gambling", "DVM-BASIC", "cryptocurrency games", "random selection", "DERO smart contracts", "blockchain gaming", "provably fair lottery"] date: "2024-08-26" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/lottery-contract.jpeg" slug: "lottery-smart-contract" canonicalUrl: "https://derod.org/smartContracts/lottery" tags: ["smart-contract", "lottery", "gaming", "tutorial", "code-example"] --- # Lottery Smart Contract Guide **Testnet Tutorial:** This guide uses testnet ports (40402/40403). Always test smart contracts on testnet before deploying to mainnet. For mainnet, use ports **10102** (daemon) and **10103** (wallet). #### Dero Stargate DVM Smart Contracts guide to install and test various functions of the lottery Smart Contract. 1. Download Dero Stargate testnet source and binaries. 2. Start Dero daemon in testnet mode: ```bash ./derod-linux-amd64 --testnet ``` 3. Start Dero wallet in testnet: ```bash ./dero-wallet-cli-linux-amd64 --rpc-server --wallet-file testnet.wallet --testnet ``` 4. Start a second Dero wallet instance to test transfer/ownership functions, etc.: ```bash ./dero-wallet-cli-linux-amd64 --wallet-file testnet2.wallet --testnet --rpc-server --rpc-bind=127.0.0.1:40404 ``` 5. Dero testnet Explorer: ```bash ./explorer-linux-amd64 --rpc-server-address 127.0.0.1:40402 --http-address=0.0.0.0:8080 ``` - [Dero Stargate Testnet Explorer](https://testnetexplorer.derofoundation.org/) ### Installing Smart Contract ```bash curl --request POST --data-binary @lottery.bas http://127.0.0.1:40403/install_sc ``` ### Download SC Code, Check Balance, and Variables from SC ```bash curl http://127.0.0.1:40402/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"getsc","params":{"scid":"30b84e9ab5baeee7195e7e1ccb1f533b7402beb2d3cfa97216a6d80c01056f66", "code":true}}' -H 'Content-Type: application/json' curl http://127.0.0.1:40402/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"getsc","params":{"scid":"30b84e9ab5baeee7195e7e1ccb1f533b7402beb2d3cfa97216a6d80c01056f66", "code":false, "keysstring":["deposit_count"]}}' -H 'Content-Type: application/json' ``` ### Examples of Various Lottery Smart Contract Functions #### Play Lottery This function enters the lottery by sending DERO to the contract. The value parameter is set by the deposit amount. ```bash curl http://127.0.0.1:40403/json_rpc -d '{ "jsonrpc": "2.0", "id": "0", "method": "scinvoke", "params": { "sc_dero_deposit": 200000, "scid": "30b84e9ab5baeee7195e7e1ccb1f533b7402beb2d3cfa97216a6d80c01056f66", "sc_rpc": [ {"name": "entrypoint", "datatype": "S", "value": "Lottery"} ] } }' -H 'Content-Type: application/json' ``` *Note: When deposit_count reaches the value set in lotteryeveryXdeposit (default is 2), the lottery will trigger and randomly select a winner from all participants.* #### Withdraw Balance (Smart Contract Owner Only) The contract owner can withdraw accumulated fees from the contract. ```bash curl http://127.0.0.1:40403/json_rpc -d '{ "jsonrpc": "2.0", "id": "0", "method": "scinvoke", "params": { "scid": "30b84e9ab5baeee7195e7e1ccb1f533b7402beb2d3cfa97216a6d80c01056f66", "sc_rpc": [ {"name": "entrypoint", "datatype": "S", "value": "Withdraw"}, {"name": "amount", "datatype": "U", "value": 100000} ] } }' -H 'Content-Type: application/json' ``` #### Transfer Ownership (Owner Only) Initiates the ownership transfer process. The new owner must claim ownership to complete the transfer. ```bash curl http://127.0.0.1:40403/json_rpc -d '{ "jsonrpc": "2.0", "id": "0", "method": "scinvoke", "params": { "scid": "30b84e9ab5baeee7195e7e1ccb1f533b7402beb2d3cfa97216a6d80c01056f66", "sc_rpc": [ {"name": "entrypoint", "datatype": "S", "value": "TransferOwnership"}, {"name": "newowner", "datatype": "S", "value": "deto1qy..."} ] } }' -H 'Content-Type: application/json' ``` #### Claim Ownership (New Owner Only) The designated new owner must call this function to complete the ownership transfer process. ```bash curl http://127.0.0.1:40403/json_rpc -d '{ "jsonrpc": "2.0", "id": "0", "method": "scinvoke", "params": { "scid": "30b84e9ab5baeee7195e7e1ccb1f533b7402beb2d3cfa97216a6d80c01056f66", "sc_rpc": [ {"name": "entrypoint", "datatype": "S", "value": "ClaimOwnership"} ] } }' -H 'Content-Type: application/json' ``` #### Update Code (Owner Only) Allows the owner to update the smart contract code. Use with caution as this changes the contract behavior. ```bash curl http://127.0.0.1:40403/json_rpc -d '{ "jsonrpc": "2.0", "id": "0", "method": "scinvoke", "params": { "scid": "30b84e9ab5baeee7195e7e1ccb1f533b7402beb2d3cfa97216a6d80c01056f66", "sc_rpc": [ {"name": "entrypoint", "datatype": "S", "value": "UpdateCode"}, {"name": "code", "datatype": "S", "value": "/* Lottery Smart Contract */\nFunction Initialize() Uint64\n..."} ] } }' -H 'Content-Type: application/json' ``` #### Tune Lottery Parameters (Owner Only) Adjust how frequently the lottery runs and the percentage of deposits returned to winners. ```bash curl http://127.0.0.1:40403/json_rpc -d '{ "jsonrpc": "2.0", "id": "0", "method": "scinvoke", "params": { "scid": "30b84e9ab5baeee7195e7e1ccb1f533b7402beb2d3cfa97216a6d80c01056f66", "sc_rpc": [ {"name": "entrypoint", "datatype": "S", "value": "TuneLotteryParameters"}, {"name": "lotteryeveryXdeposit", "datatype": "U", "value": 5}, {"name": "lotterygiveback", "datatype": "U", "value": 9800} ] } }' -H 'Content-Type: application/json' ``` *Note: lotterygiveback is measured in basis points (1/100 of a percent). 9800 means 98% returned to winners, 2% kept as fees.* ## Lottery.bas ```DVM-BASIC /* Lottery Smart Contract in DVM-BASIC This lottery smart contract will give lottery wins every xth try. */ Function Lottery(value Uint64) Uint64 10 dim deposit_count,winner as Uint64 20 LET deposit_count = LOAD("deposit_count")+1 25 IF value == 0 THEN GOTO 110 // if deposit amount is 0, simply return 30 STORE("depositor_address" + (deposit_count-1), SIGNER()) // store address for later on payment 40 STORE("deposit_total", LOAD("deposit_total") + value ) 50 STORE("deposit_count", deposit_count) 60 IF LOAD("lotteryeveryXdeposit") > deposit_count THEN GOTO 110 // wait till X players join in 70 LET winner = RANDOM() % deposit_count // we have a winner 80 SEND_DERO_TO_ADDRESS(LOAD("depositor_address" + winner) , LOAD("lotterygiveback")*LOAD("deposit_total")/10000) // Reinitialize for another round 90 STORE("deposit_count", 0) // initial players 100 STORE("deposit_total", 0) // total deposit of all players 110 RETURN 0 End Function // Function used to initialize parameters during install time Function Initialize() Uint64 10 STORE("owner", SIGNER()) // store in DB ["owner"] = address 20 STORE("lotteryeveryXdeposit", 2) // lottery rewards every X deposits 30 STORE("lotterygiveback", 9900) // lottery gives back 99% of deposits, 1% accumulated for owner to withdraw 33 STORE("deposit_count", 0) // initial players 34 STORE("deposit_total", 0) // total deposit of all players // 35 printf "Initialize executed" 40 RETURN 0 End Function // Used to tune lottery parameters Function TuneLotteryParameters(lotteryeveryXdeposit Uint64, lotterygiveback Uint64) Uint64 10 dim key, stored_owner as String 20 dim value_uint64 as Uint64 30 IF LOAD("owner") == SIGNER() THEN GOTO 100 // check whether owner is real owner 40 RETURN 1 // non-zero return means error: not owner 100 STORE("lotteryeveryXdeposit", lotteryeveryXdeposit) // lottery rewards every X deposits 130 STORE("lotterygiveback", lotterygiveback) // lottery gives back in 1/10000 parts, granularity .01% 140 RETURN 0 // zero return means success End Function // Function used to change owner, owner is a string form of address Function TransferOwnership(newowner String) Uint64 10 IF LOAD("owner") == SIGNER() THEN GOTO 30 20 RETURN 1 30 STORE("tmpowner", ADDRESS_RAW(newowner)) 40 RETURN 0 End Function // Until the new owner claims ownership, the existing owner remains the owner Function ClaimOwnership() Uint64 10 IF LOAD("tmpowner") == SIGNER() THEN GOTO 30 20 RETURN 1 30 STORE("owner", SIGNER()) // ownership claim successful 40 RETURN 0 End Function // If signer is the owner, withdraw any requested funds Function Withdraw(amount Uint64) Uint64 10 IF LOAD("owner") == SIGNER() THEN GOTO 30 20 RETURN 1 30 SEND_DERO_TO_ADDRESS(SIGNER(), amount) 40 RETURN 0 End Function // If signer is the owner, provide rights to update code anytime Function UpdateCode(code String) Uint64 10 IF LOAD("owner") == SIGNER() THEN GOTO 30 20 RETURN 1 30 UPDATE_SC_CODE(code) 40 RETURN 0 End Function ``` --- ## Related Pages **Learn Smart Contract Programming:** - [DVM-BASIC Programming Guide](/dvm/dvm-basic.md) - Complete language reference - [DERO Virtual Machine](/dvm/dero-virtual-machine.md) - Virtual machine overview **Other Smart Contract Examples:** - [Token Contract](/smartContracts/token.md) - Private token implementation - [Assets Exchange](/smartContracts/assets.md) - Token swap contract - [Name Service](/smartContracts/name.md) - Register usernames **Deploy & Test:** - [Wallet RPC API](/rpc-api/wallet-rpc-api.md) - Deploy contracts via RPC - [Running a Node](/basics/running-a-node.md) - Setup testnet for development --- --- title: "DERO Name Service: Blockchain Username Registration | DERO Blockchain" description: "Learn how to register and manage human-readable usernames on the DERO blockchain using the built-in Name Service smart contract for easy wallet addressing." keywords: ["DERO Name Service", "blockchain usernames", "crypto wallet names", "DVM-BASIC", "wallet addressing", "name registration", "blockchain identities", "DERO usernames", "wallet aliases", "decentralized names"] date: "2024-08-26" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/name-service.jpeg" slug: "name" canonicalUrl: "https://derod.org/smartContracts/name" tags: ["smart-contracts", "name-service", "DVM-BASIC", "usernames"] --- ## Nameservice **Testnet Tutorial:** This guide uses testnet ports (40402/40403). Always test smart contracts on testnet before deploying to mainnet. For mainnet, use ports **10102** (daemon) and **10103** (wallet). Register and associate a DERO wallet with a username using the Nameservice. It includes instructions for checking the availability of a username and the process to register it with the associated DERO wallet using specific cURL commands. ### Step 1 Check whether the username is already registered. You cannot register the username if it's already taken. ```bash curl http://127.0.0.1:40402/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"nametoaddress","params":{"name":"TESTUSERNAME" }}' -H 'Content-Type: application/json' ``` ### Step 2 Register and associate a DERO wallet with the username. ```bash curl http://127.0.0.1:40403/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"scinvoke","params":{"scid":"0000000000000000000000000000000000000000000000000000000000000001","ringsize":2, "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"Register"}, {"name":"name","datatype":"S","value":"TESTUSERNAME" }] }}' -H 'Content-Type: application/json' ``` **Note:** - Replace "TESTUSERNAME" with your desired available username in the above steps. - `"scid":"0000000000000000000000000000000000000000000000000000000000000001"` is reserved for nameservice registration. ## nameservice.bas ```DVM-BASIC /* Name Service SMART CONTRACT in DVM-BASIC. Allows a user to register names which could be looked by wallets for easy to use name while transfer */ // This function is used to initialize parameters during install time Function Initialize() Uint64 10 RETURN 0 End Function // Register a name, limit names of 5 or less length Function Register(name String) Uint64 10 IF EXISTS(name) THEN GOTO 50 // if name is already used, it cannot be re-registered 20 IF STRLEN(name) >= 6 THEN GOTO 40 30 IF SIGNER() != address_raw("deto1qyvyeyzrcm2fzf6kyq7egkes2ufgny5xn77y6typhfx9s7w3mvyd5qqynr5hx") THEN GOTO 50 40 STORE(name,SIGNER()) 50 RETURN 0 End Function // This function is used to change owner // owner is a string form of address Function TransferOwnership(name String,newowner String) Uint64 10 IF LOAD(name) != SIGNER() THEN GOTO 30 20 STORE(name,ADDRESS_RAW(newowner)) 30 RETURN 0 End Function ``` --- ## Related Pages **Learn the Language:** - [DVM-BASIC Programming Guide](/dvm/dvm-basic.md) - Smart contract language guide - [DERO Virtual Machine](/dvm/dero-virtual-machine.md) - How the DVM works **Understand DERO Features:** - [DERO Usernames](/features/usernames.md) - Built-in name service explained - [Privacy Features](/privacy/index.md) - Full privacy suite overview **More Smart Contract Examples:** - [Token Contract](/smartContracts/token.md) - Private token implementation - [Assets Exchange](/smartContracts/assets.md) - Token swap contract - [Lottery Contract](/smartContracts/lottery.md) - Decentralized lottery **API References:** - [Daemon RPC API](/rpc-api/daemon-rpc-api.md) - Check name registration - [Wallet RPC API](/rpc-api/wallet-rpc-api.md) - Register names via RPC --- --- title: "DERO Token Smart Contract Guide: Implementation Tutorial | DERO Blockchain" description: "Complete guide to creating, deploying, and managing private token smart contracts on DERO blockchain, with examples for token issuance and ownership management." keywords: ["DERO tokens", "token smart contract", "private tokens", "DVM-BASIC", "token creation", "smart contract deployment", "cryptocurrency tokens", "token exchange", "DERO development", "blockchain tokens"] date: "2024-08-26" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/token-contract.jpeg" slug: "token" canonicalUrl: "https://derod.org/smartContracts/token" tags: ["smart-contracts", "tokens", "DVM-BASIC", "tutorial", "development"] --- # Token Smart Contract Guide **Testnet Tutorial:** This guide uses testnet ports (40402/40403). Always test smart contracts on testnet before deploying to mainnet. For mainnet, use ports **10102** (daemon) and **10103** (wallet). Dero Stargate DVM Smart Contracts guide to install and test various functions of the private token Smart Contract. ### Notes: 1. All wallet addresses need to be registered first with SC before interacting with it. This condition will be removed in the future. 2. The requirement of `detoAnyRandomAddressFromExplorer` during SC invocation will be removed in the future. 3. Burn is equal to deposit if SCID is defined, else DERO/token will disappear/burn from the network forever. Burn will be renamed to something more meaningful. This can be proved with cryptographic proof. ### Instructions: 1. Download DERO Stargate testnet source and binaries from [GitHub](https://github.com/deroproject/derohe/releases). 2. Start Dero daemon in testnet mode: ```shell ./derod-linux-amd64 --testnet ``` 3. Start Dero wallet in testnet: ```shell ./dero-wallet-cli-linux-amd64 --rpc-server --wallet-file testnet.wallet --testnet ``` 4. Start a second instance of Dero wallet to test transfer/ownership functions, etc.: ```shell ./dero-wallet-cli-linux-amd64 --wallet-file testnet2.wallet --testnet --rpc-server --rpc-bind=127.0.0.1:40404 ``` 5. Dero testnet Explorer: [Testnet Explorer](https://testnetexplorer.derofoundation.org/) ### Commands: To send DERO to multiple users in one transaction: ```shell curl http://127.0.0.1:40403/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"transfer","params":{"transfers":[{"amount":100000,"destination":"deto1ADDRESS1"},{"amount":300000,"destination":"deto1ADDRESS12"}]}}' -H 'Content-Type: application/json' ``` DERO has two types of SCs: public and private. 1. Public SCs are public with all data/code/exchanges available to the public. 2. Private SCs have their smart contract data public, but no one knows the specific details of users' token ownership or transactions. It's like cash in a bank; once it's withdrawn, the bank doesn't know who has what amount or how it's used/sent/received. ### Installing Private Smart Contract: Download `token.bas` [here](https://git.derofoundation.org/DeroProject/derosuite_stargate/src/master/cmd/dvm/token.bas). ```shell curl --request POST --data-binary @token.bas http://127.0.0.1:40403/install_sc ``` To check private token balance in the wallet: ```shell balance SCID ``` Download SC code, check SC balance, and variables from the chain: ```shell curl http://127.0.0.1:40402/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"getsc","params":{"scid":"aacaa7bb2388d06e523e5bc0783e4e131738270641406c12978155ba033373af", "code":true}}' -H 'Content-Type: application/json' ``` ### Examples of Various Functions: - Send private tokens from one wallet to another wallet: ```shell curl http://127.0.0.1:40403/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"transfer","params":{"transfers":[{"amount":111111,"destination":"deto1qxqqen6lqmksmzmxmfqmxp2y8zvkldtcq8jhkzqflmyczepjw9dp46gc3cczu"},{"amount":333333,"destination":"deto1qxqqen6lqmksmzmxmfqmxp2y8zvkldtcq8jhkzqflmyczepjw9dp46gc3cczu","scid": "aacaa7bb2388d06e523e5bc0783e4e131738270641406c12978155ba033373af"}]}}' -H 'Content-Type: application/json' ``` - Convert DERO to tokens 1:1 swap: ```shell curl http://127.0.0.1:40403/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"transfer","params":{"transfers":[{"amount":1,"destination":"deto1qxqqen6lqmksmzmxmfqmxp2y8zvkldtcq8jhkzqflmyczepjw9dp46gc3cczu", "burn":44}],"scid":"aacaa7bb2388d06e523e5bc0783e4e131738270641406c12978155ba033373af", "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"IssueTOKENX"}]}}' -H 'Content-Type: application/json' ``` - Convert tokens to DERO 1:1 swap: ```shell curl http://127.0.0.1:40403/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"transfer","params":{"transfers":[{"scid":"aacaa7bb2388d06e523e5bc0783e4e131738270641406c12978155ba033373af", "amount":1,"destination":"deto1qxqqen6lqmksmzmxmfqmxp2y8zvkldtcq8jhkzqflmyczepjw9dp46gc3cczu", "burn":9}],"scid":"aacaa7bb2388d06e523e5bc0783e4e131738270641406c12978155ba033373af", "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"ConvertTOKENX"}]}}' -H 'Content-Type: application/json' ``` - Withdraw balance only for the smart contract owner: ```shell curl http://127.0.0.1:40403/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"transfer","params":{"transfers":[{"amount":111111,"destination":"deto1qxqqen6lqmksmzmxmfqmxp2y8zvkldtcq8jhkzqflmyczepjw9dp46gc3cczu"}],"scid":"aacaa7bb2388d06e523e5bc0783e4e131738270641406c12978155ba033373af", "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"Withdraw"}, {"name":"amount","datatype":"U","value":2}]}}' -H 'Content-Type: application/json' ``` - Transfer ownership of the smart contract to a new address/owner: ```shell curl http://127.0.0.1:40403/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"transfer","params":{"transfers":[{"amount":111111,"destination":"deto1qxqqen6lqmksmzmxmfqmxp2y8zvkldtcq8jhkzqflmyczepjw9dp46gc3cczu"}],"scid":"aacaa7bb2388d06e523e5bc0783e4e131738270641406c12978155ba033373af", "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"TransferOwnership"}, {"name":"newowner","datatype":"S","value":"deto1qxsplx7vzgydacczw6vnrtfh3fxqcjevyxcvlvl82fs8uykjkmaxgfgulfha5"}]}}' -H 'Content-Type: application/json' ``` - Claim ownership of the smart contract: ```shell curl http://127.0.0.1:40403/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"transfer","params":{"transfers":[{"amount":111111,"destination":"deto1qxqqen6lqmksmzmxmfqmxp2y8zvkldtcq8jhkzqflmyczepjw9dp46gc3cczu"}],"scid":"aacaa7bb2388d06e523e5bc0783e4e131738270641406c12978155ba033373af", "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"ClaimOwnership"}]}}' -H 'Content-Type: application/json' ``` - Update smart contract code: ```shell curl http://127.0.0.1:40403/json_rpc -d '{"jsonrpc":"2.0","id":"0","method":"transfer","params":{"transfers":[{"amount":111111,"destination":"deto1qxqqen6lqmksmzmxmfqmxp2y8zvkldtcq8jhkzqflmyczepjw9dp46gc3cczu"}],"scid":"aacaa7bb2388d06e523e5bc0783e4e131738270641406c12978155ba033373af", "sc_rpc":[{"name":"entrypoint","datatype":"S","value":"UpdateCode"}, {"name":"code","datatype":"S","value":"new code should be placed here"}]}}' -H 'Content-Type: application/json' ``` DERO Smart Contracts Tokens privacy can be understood just like banks handle cash. Once cash is out from the bank, the bank is not aware of it (who owns what value) until it is deposited back. The smart contract only maintains supply and other necessary items to keep it working. DERO Tokens can be transferred to other wallets just like native DERO with Homomorphic Encryption and without involvement of issuing Smart Contracts. Token issuing Smart Contract cannot hold/freeze/control their tokens once they are issued and sent to any wallet. This token is Private. Use `Function InitializePrivate() Uint64` to make any Smart Contract private. ## token.bas ```DVM-BASIC /* Private Token Smart Contract Example in DVM-BASIC. */ /* Issue tokens after depositing DERO (Convert DERO to TOKENX) */ Function IssueTOKENX() Uint64 10 SEND_ASSET_TO_ADDRESS(SIGNER(), DEROVALUE(), SCID()) // Increment balance of user, without knowing the original balance, this is done homomorphically 20 RETURN 0 End Function /* Convert TOKENX to DERO after depositing TOKENX. Smart Contract can give DERO, Only if DERO balance exists. */ Function ConvertTOKENX() Uint64 10 SEND_DERO_TO_ADDRESS(SIGNER(), ASSETVALUE(SCID())) // Increment balance of user, without knowing the original balance, this is done using Homomorphic Encryption. 20 RETURN 0 End Function /* This function is used to initialize parameters during install time InitializePrivate initializes a private SC */ Function InitializePrivate() Uint64 10 STORE("owner", SIGNER()) // Store in DB ["owner"] = address 30 SEND_ASSET_TO_ADDRESS(SIGNER(), 1600000, SCID()) // Gives initial encrypted balance of 1600000. 40 RETURN 0 End Function /* This function is used to change owner owner is a string form of an address */ Function TransferOwnership(newowner String) Uint64 10 IF LOAD("owner") == SIGNER() THEN GOTO 30 20 RETURN 1 30 STORE("tmpowner", ADDRESS_RAW(newowner)) 40 RETURN 0 End Function /* Until the new owner claims ownership, the existing owner remains the owner */ Function ClaimOwnership() Uint64 10 IF LOAD("tmpowner") == SIGNER() THEN GOTO 30 20 RETURN 1 30 STORE("owner", SIGNER()) // ownership claim successful 40 RETURN 0 End Function /* If signer is owner, withdraw any requested funds if everything is okay, they will be showing in the signer's wallet */ Function Withdraw(amount Uint64) Uint64 10 IF LOAD("owner") == SIGNER() THEN GOTO 30 20 RETURN 1 30 SEND_DERO_TO_ADDRESS(SIGNER(), amount) 40 RETURN 0 End Function /* If signer is the owner, provide him rights to update code anytime make sure the update is always available to the SC */ Function UpdateCode(code String) Uint64 10 IF LOAD("owner") == SIGNER() THEN GOTO 30 20 RETURN 1 30 UPDATE_SC_CODE(code) 40 RETURN 0 End Function ``` --- ## Related Pages **Learn the Language:** - [DVM-BASIC Programming Guide](/dvm/dvm-basic.md) - Smart contract language syntax - [DERO Virtual Machine](/dvm/dero-virtual-machine.md) - How the DVM works **Understand Tokens:** - [DERO Tokens Overview](/basics/tokens.md) - Token privacy and features - [Homomorphic Encryption](/privacy/homomorphic-encryption.md) - How private balances work **Build & Deploy:** - [Wallet RPC API](/rpc-api/wallet-rpc-api.md) - Deploy and interact with contracts - [Assets Exchange](/smartContracts/assets.md) - Token swap contract example - [Name Service](/smartContracts/name.md) - Register names for easy addressing --- --- title: "DERO dApps: Private Decentralized Applications | DERO Blockchain" description: "Explore decentralized applications (dApps) on DERO - the first blockchain with private smart contracts using homomorphic encryption. Build censorship-resistant apps with DVM-BASIC." keywords: ["DERO dApps", "Decentralized Applications", "private smart contracts", "DVM-BASIC", "homomorphic encryption", "DERO ecosystem", "blockchain apps", "privacy dApps"] date: "2024-08-26" lastUpdated: "2025-10-24" authors: ["DHEBP"] image: "/assets/dapps.jpeg" slug: "dapps" canonicalUrl: "https://derod.org/tools/dapps" tags: ["tools", "dApps", "smart-contracts", "DVM", "applications", "privacy"] --- # DERO dApps: Private Decentralized Applications ![Decentralized Applications](/assets/dapps.jpeg) **Decentralized Applications (dApps)** are applications that run on blockchain technology rather than centralized servers. They operate on distributed networks where no single authority can control, censor, or shut them down. > [!NOTE] > **DERO's Unique Advantage:** The world's first blockchain with **private smart contracts** using homomorphic encryption. Your dApp code is public and auditable, but all **balances, amounts, and financial data** remain encrypted on-chain. --- ## What Makes DERO dApps Special? ```mermaid graph LR A[DERO dApp] --> B[Public Code] A --> C[Encrypted Balances] A --> D[Private State] A --> E[Provable Execution] B --> F[Auditable Logic] C --> G[Hidden Amounts] D --> H[Confidential Data] E --> I[Zero-Knowledge Proofs] ``` | Feature | Traditional Blockchains | DERO | |---------|------------------------|------| | **Smart Contracts** | โœ… Public | โœ… Private | | **Balances** | โŒ Visible | โœ… Encrypted (Homomorphic) | | **Transaction Amounts** | โŒ Public | โœ… Hidden (Bulletproofs) | | **Contract State** | โŒ All visible | โœ… Financial data encrypted | | **Speed** | ~15-60 seconds | โšก ~18 seconds | --- ## DERO dApp Categories ### ๐Ÿฆ **DeFi (Decentralized Finance)** Build financial applications with complete privacy: - **Private DEXs** - Swap tokens without revealing amounts - **Anonymous Escrow** - Trustless transactions with hidden balances - **Private Lending** - Collateralized loans with encrypted positions - **Yield Vaults** - Staking rewards without exposing holdings **Example:** Private token swap where neither party knows the other's total balance. ### ๐ŸŽฎ **Gaming & Entertainment** Privacy-enhanced gaming experiences: - **Provably Fair Gambling** - Lottery, poker, baccarat with on-chain randomness - **Play-to-Earn** - Hidden inventory and earnings - **Virtual Assets** - Private ownership of in-game items - **Tournament Platforms** - Anonymous competitive gaming **Example:** Poker game where hand values and bet amounts remain hidden until reveal. ### ๐Ÿ’ฌ **Social & Communication** Censorship-resistant platforms: - **Anonymous Forums** - Decentralized message boards (DEchan) - **Private Messaging** - On-chain encrypted communication - **Content Platforms** - Creator monetization without intermediaries - **Voting Systems** - Anonymous governance with verifiable results ### ๐Ÿ›’ **Marketplaces & Commerce** Private peer-to-peer commerce: - **Anonymous Marketplaces** - Buy/sell without exposing wallet balances - **Digital Goods** - NFTs with private metadata - **Service Platforms** - Freelance work with encrypted payments - **Supply Chain** - Track goods with selective disclosure ### ๐Ÿ”ง **Infrastructure** Decentralized services: - **Name Service** - Human-readable addresses (like ENS) - **Storage Pointers** - Decentralized file references - **Oracle Services** - Private data feeds - **Identity Solutions** - Anonymous authentication --- ## Building Your First DERO dApp ### 1. Write Smart Contract in DVM-BASIC DVM-BASIC is a BASIC-like language designed for the DERO Virtual Machine: ```basic /* Simple Lottery Smart Contract */ Function Initialize() Uint64 10 STORE("owner", SIGNER()) 20 STORE("deposit_count", 0) 30 STORE("deposit_total", 0) 40 RETURN 0 End Function Function Lottery() Uint64 10 dim deposit_count, winner as Uint64 20 LET deposit_count = LOAD("deposit_count") + 1 // Check if deposit is valid 25 IF DEROVALUE() == 0 THEN GOTO 110 // Store depositor 30 STORE("depositor_address" + (deposit_count-1), SIGNER()) 40 STORE("deposit_total", LOAD("deposit_total") + DEROVALUE()) 50 STORE("deposit_count", deposit_count) // Wait for 2 players 60 IF 2 > deposit_count THEN GOTO 110 // Pick winner using on-chain randomness 70 LET winner = RANDOM() % deposit_count 80 SEND_DERO_TO_ADDRESS(LOAD("depositor_address" + winner), LOAD("deposit_total")) // Reset for next round 90 STORE("deposit_count", 0) 100 STORE("deposit_total", 0) 110 RETURN 0 End Function ``` **Key DVM-BASIC Features:** - โœ… `STORE()` / `LOAD()` - Persistent encrypted storage - โœ… `SIGNER()` - Get transaction sender - โœ… `DEROVALUE()` - Amount sent with transaction - โœ… `RANDOM()` - Deterministic on-chain randomness - โœ… `SEND_DERO_TO_ADDRESS()` - Send funds programmatically ### 2. Deploy via Wallet RPC **Method 1: Using Wallet RPC Endpoint** ```bash # Deploy smart contract curl --request POST \ --data-binary @lottery.bas \ http://127.0.0.1:10103/install_sc # Returns: { "txid": "abc123...", "scid": "def456..." } ``` **Method 2: Using Wallet RPC JSON-RPC** ```bash # Install smart contract via scinvoke curl -X POST http://127.0.0.1:10103/json_rpc \ -H "Content-Type: application/json" \ -d '{ "jsonrpc": "2.0", "id": "1", "method": "transfer", "params": { "scid": "", "sc_rpc": [ {"name": "SC_ACTION", "datatype": "U", "value": 0}, {"name": "SC_CODE", "datatype": "S", "value": ""} ], "ringsize": 16 } }' ``` ### 3. Interact with Contract **Call smart contract function:** ```bash # Call Lottery() function with 5 DERO deposit curl http://127.0.0.1:10103/json_rpc -d '{ "jsonrpc": "2.0", "id": "1", "method": "scinvoke", "params": { "scid": "YOUR_SCID_HERE", "sc_dero_deposit": 500000, "ringsize": 16, "sc_rpc": [ {"name": "entrypoint", "datatype": "S", "value": "Lottery"} ] } }' -H 'Content-Type: application/json' ``` ### 4. Query Contract State **Get contract balance and variables:** ```bash # Query smart contract curl http://127.0.0.1:10102/json_rpc -d '{ "jsonrpc": "2.0", "id": "1", "method": "DERO.GetSC", "params": { "scid": "YOUR_SCID_HERE", "code": true, "variables": true } }' -H 'Content-Type: application/json' ``` **Response:** ```json { "result": { "balance": 1000000, "code": "...", "balances": { "deposit_count": 5, "deposit_total": 1000000, "owner": "deto1qy..." } } } ``` --- ## Building a Web Front-End ### Option 1: Direct JSON-RPC (No Dependencies) ```javascript // Simple JavaScript RPC client async function callSmartContract(scid, entrypoint, deroDeposit = 0) { const response = await fetch('http://127.0.0.1:10103/json_rpc', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ jsonrpc: '2.0', id: '1', method: 'scinvoke', params: { scid: scid, sc_dero_deposit: deroDeposit, ringsize: 16, sc_rpc: [ { name: 'entrypoint', datatype: 'S', value: entrypoint } ] } }) }); return await response.json(); } // Get contract state async function getContractState(scid) { const response = await fetch('http://127.0.0.1:10102/json_rpc', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ jsonrpc: '2.0', id: '1', method: 'getsc', params: { scid: scid, code: false, variables: true } }) }); return await response.json(); } // Usage const txid = await callSmartContract( 'YOUR_SCID', 'Lottery', 500000 // 5 DERO ); console.log('Transaction:', txid); const state = await getContractState('YOUR_SCID'); console.log('Contract state:', state.result.balances); ``` ### Option 2: XSWD Wallet Integration (Recommended) For production dApps that need wallet connection: ```javascript // Using XSWD for wallet integration // Connect to user's wallet await xswd.initialize(); // Request wallet connection const walletInfo = await xswd.wallet.GetAddress(); console.log('Connected wallet:', walletInfo.address); // Call smart contract through user's wallet const result = await xswd.wallet.scinvoke({ scid: 'YOUR_SCID', sc_dero_deposit: 500000, ringsize: 16, sc_rpc: [ { name: 'entrypoint', datatype: 'S', value: 'Lottery' } ] }); console.log('TXID:', result.txid); ``` **See full XSWD guide:** [XSWD Integration](/tools/xswd.md) --- ## Development Tools ### dSlate - Visual Smart Contract Builder > [!NOTE] > **[dSlate](https://forum.dero.io/t/dapp-building-and-learning-tool-dslate/2204)** is a GUI tool for building and testing DERO smart contracts without command-line knowledge. **Features:** - ๐Ÿ“ Code editor with syntax highlighting - ๐Ÿงช Built-in testing environment - ๐Ÿš€ One-click deployment - ๐Ÿ“Š Contract state visualization - ๐Ÿ’พ Template library ### Local Development Environment **1. Run simulator node:** ```bash # Start local test blockchain ./derod-linux-amd64 --simulator ``` **2. Create test wallet:** ```bash # Create wallet for testing ./dero-wallet-cli-linux-amd64 --wallet-file test.db ``` **3. Deploy and test:** ```bash # Deploy contract curl --request POST --data-binary @contract.bas \ http://127.0.0.1:30000/install_sc # Test interaction curl http://127.0.0.1:30000/json_rpc -d '{ "method": "scinvoke", "params": { "scid": "YOUR_TEST_SCID", "sc_rpc": [...] } }' ``` --- ## Production Deployment Checklist > [!WARNING] > **Before deploying to mainnet**, ensure you've completed all testing! ### Pre-Launch - [ ] **Test extensively** on simulator node - [ ] **Deploy to testnet** and run for 1+ weeks - [ ] **Security audit** - Have community review code - [ ] **Gas optimization** - Minimize transaction costs - [ ] **Documentation** - Write clear user guide - [ ] **Front-end testing** - Test all user flows - [ ] **Emergency functions** - Add pause/upgrade mechanisms ### Launch - [ ] **Deploy to mainnet** with appropriate ring size (16+) - [ ] **Publish SCID** - Share smart contract ID - [ ] **Open-source code** - GitHub repository - [ ] **Community announcement** - DERO Discord/Forum - [ ] **Monitor usage** - Track contract calls and state - [ ] **Bug bounty** - Incentivize security research ### Post-Launch - [ ] **User support** - Answer questions, fix issues - [ ] **Updates** - Release improvements via update function - [ ] **Analytics** - Track adoption and usage metrics - [ ] **Marketing** - Promote to DERO community --- ## Smart Contract Security ### Common Pitfalls โŒ **Don't:** - Store sensitive data in plaintext (even encrypted blockchain leaks some info) - Use predictable randomness (always use RANDOM() function) - Skip input validation - Allow reentrancy attacks - Forget to check SIGNER() authorization โœ… **Do:** - Use STORE() for all persistent data - Validate all inputs and amounts - Check SIGNER() for owner-only functions - Use LOAD() safely (check for existence) - Add emergency pause mechanisms - Include UpdateCode() function for bug fixes ### Example: Secure Owner Pattern ```basic Function Initialize() Uint64 10 STORE("owner", SIGNER()) 20 RETURN 0 End Function Function TransferOwnership(newowner String) Uint64 // Check caller is current owner 10 IF LOAD("owner") == SIGNER() THEN GOTO 30 20 RETURN 1 // Unauthorized // Store new owner 30 STORE("tmpowner", ADDRESS_RAW(newowner)) 40 RETURN 0 End Function Function ClaimOwnership() Uint64 // New owner must claim 10 IF LOAD("tmpowner") == SIGNER() THEN GOTO 30 20 RETURN 1 30 STORE("owner", SIGNER()) 40 RETURN 0 End Function Function UpdateCode(code String) Uint64 // Only owner can update 10 IF LOAD("owner") == SIGNER() THEN GOTO 30 20 RETURN 1 30 UPDATE_SC_CODE(code) 40 RETURN 0 End Function ``` --- ## Learning Resources ### Official Documentation - ๐Ÿ“˜ **[DERO Documentation](https://docs.derofoundation.org)** - Complete developer docs - ๐ŸŽ“ **[DVM-BASIC Guide](/dvm/dvm-basic.md)** - Smart contract language reference - ๐Ÿ”Œ **[RPC API Reference](/rpc-api/wallet-rpc-api.md)** - Wallet and daemon APIs - ๐Ÿ” **[XSWD Protocol](/tools/xswd.md)** - Wallet integration guide ### Community Resources - ๐Ÿ’ฌ **[DERO Discord](https://discord.gg/H95TJDp)** - Live developer chat - ๐Ÿ“– **[DERO Wiki](https://wiki.derofoundation.org)** - Community knowledge base - ๐Ÿ› **[GitHub](https://github.com/deroproject/derohe)** - Source code & issues - ๐Ÿ—ฃ๏ธ **[DERO Forum](https://forum.dero.io)** - Long-form discussions ### Example Projects Browse working smart contracts in the [DERO GitHub](https://github.com/deroproject/derohe/tree/main/blockchain/hardcoded_sc): - **Name Service** - Address registration system - **Lottery** - Provably fair gaming - **Token Standards** - Asset creation templates --- ## Why Build on DERO? | Advantage | Impact | |-----------|--------| | ๐Ÿ”’ **Privacy by Default** | Users transact without exposing balances | | โšก **Fast Finality** | 18-second blocks, ~1 minute confirmation | | ๐Ÿ’ช **Homomorphic Encryption** | Compute on encrypted data | | ๐ŸŽฏ **Small Contracts** | Fixed ~2.5KB transactions regardless of complexity | | ๐Ÿ” **Battle-Tested** | Running since 2017, proven security | | ๐ŸŒ **No Gas Wars** | Predictable, fair transaction fees | | ๐Ÿ‘ฅ **Active Community** | Supportive developers and users | --- ## Get Started Ready to build the next private dApp? 1. **[Download DERO](/basics/running-a-node.md)** - Set up local node 2. **[Learn DVM-BASIC](/dvm/dvm-basic.md)** - Master smart contracts 3. **[Join Discord](https://discord.gg/H95TJDp)** - Connect with builders 4. **[Explore Examples](https://github.com/deroproject/derohe/tree/main/tests)** - Study working code > [!NOTE] > **Need help?** The DERO community is active and welcoming. Don't hesitate to ask questions in Discord or the forum! --- ## Further Reading **Core Concepts:** - [DERO Virtual Machine (DVM)](/dvm/dero-virtual-machine.md) - [Smart Contracts Overview](/features/smart-contracts.md) - [Homomorphic Encryption](/privacy/homomorphic-encryption.md) **APIs & Integration:** - [Daemon RPC API](/rpc-api/daemon-rpc-api.md) - [Wallet RPC API](/rpc-api/wallet-rpc-api.md) - [XSWD Wallet Integration](/tools/xswd.md) **Advanced Topics:** - [Private Smart Contracts](/privacy/private-smart-contracts.md) - [Bulletproofs](/privacy/bulletproofs.md) - [Ring Signatures](/privacy/ring-signatures.md) --- --- title: "Gnomon: Decentralized Blockchain Indexer | DERO Blockchain" description: "Explore Gnomon, a decentralized search engine powered by DeroHE, empowering individual user nodes by enabling direct navigation, exploration, and search within the blockchain and its smart contracts." keywords: ["Gnomon", "decentralized search engine", "DeroHE", "blockchain search", "smart contract indexing", "transaction indexing", "xtag", "blockchain indexer", "DERO tools"] date: "2024-08-26" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/gnomon.jpeg" slug: "gnomon" canonicalUrl: "https://derod.org/tools/gnomon" tags: ["tools", "gnomon", "indexer", "search", "blockchain-data"] --- # Gnomon ![Gnomon](/assets/gnomon.jpeg) ## Decentralized Search Engine DeroHE's client, powered by Gnomon, empowers individual user nodes by enabling direct navigation, exploration, and search within the blockchain and its smart contracts. This liberates users from relying on external blockchain data providers like Infura, offering more control over data access and management. Gnomon efficiently handles and arranges the gathered information, thus enhancing its operational efficiency within the decentralized ecosystem. Gnomon leverages a small selection of databases such as [BoltDB](https://pkg.go.dev/go.etcd.io/bbolt) and [GravitonDB](/features/graviton.md). Due to their key/value pair nature as well as being written entirely in Golang, they are easy choices to be leveraged for an all-go codebase. Being that they are key/value pair data structures, this makes storing and retrieving information simpler and more efficient. #### Core Features - Smart Contract querying and indexing - Transaction querying and indexing - Transaction Markup Language (xtag) support - No custom daemon, no modified code. ## Gnomon Use Cases ### GnomonIndexer (CLI) The GnomonIndexer CLI is a command-line interface used to initiate an indexer for analyzing transactions on the DERO blockchain. It is primarily designed for indexing smart contract interactions and asset transactions. Users can specify various options when running the indexer, such as the daemon RPC address and the number of parallel blocks to index. Increasing the number of parallel blocks may result in higher load on both the GnomonIndexer and the connected daemon. ### Gnomon as a Go package The Gnomon repository provides a Go package that can be imported into other Golang projects, allowing developers to leverage its functionality within their own decentralized applications (dApps) or configurations. This package offers various capabilities for tracking specific contracts or data on the DERO blockchain. ### Gnomon Smart Contract Indexing Service The Smart Contract Indexing Service by Gnomon is crucial for analyzing DERO blockchain smart contracts. It operates on-chain, indexing contracts based on defined filters or all contracts if no filter is set. Users can specify criteria like contract actions. Stored contract details include deployment height, owner identity, and SCID. The `gnomonsc` CLI configures this service, with parameters like daemon RPC address. Future enhancements aim for efficiency and off-chain data storage, though detailed plans are pending. --- --- title: "DERO MCP Server | AI Assistant Integration for the DERO Blockchain" description: "Run a read-only, agent-ready DERO MCP server โ€” stdio for local hosts, streamable-HTTP for remote agents. 21 daemon primitives + 11 composite tools (incl. TELA app inspection and dURL discovery) that fuse live chain reads with the bundled DERO docs index, plus structured errors and curated citations โ€” no middlemen, no API keys, no surveillance." keywords: ["MCP", "Model Context Protocol", "DERO", "AI assistant", "Claude Desktop", "Cursor", "OpenCode", "ChatGPT Custom Connectors", "agent", "composite tools", "read-only", "DVM", "smart contracts", "agent-ready", "streamable-HTTP", "stargate", "privacy-blockchain", "monero-alternative", "private-ethereum", "homomorphic-encryption", "ring-signatures", "bulletproofs"] date: "2025-10-19" lastUpdated: "2026-05-29" authors: ["DHEBP"] slug: "mcp-server" canonicalUrl: "https://derod.org/tools/mcp-server" tags: ["tools", "mcp", "ai", "agents", "stdio", "read-only"] --- # MCP Server Query the DERO blockchain โ€” and the canonical DERO documentation โ€” from AI assistants. No middlemen, no API keys, no surveillance. The DERO MCP server implements the [Model Context Protocol](https://modelcontextprotocol.io), the open standard for connecting AI models to external tools. Run it as a local **stdio** process for Claude Desktop / Cursor / OpenCode, or as a **streamable-HTTP** server behind your own domain (e.g. `mcp.derod.org`) for ChatGPT Custom Connectors, Cursor hosted mode, and any agent that needs a remote URL instead of a subprocess. > [!NOTE] > **AI discovery files:** [llms.txt](https://derod.org/llms.txt) and [/api/openapi.json](https://derod.org/api/openapi.json) are curated subsets for agents โ€” not a full RPC catalog. Use the [Daemon RPC API](/rpc-api/daemon-rpc-api.md) and [Wallet RPC API](/rpc-api/wallet-rpc-api.md) for complete method reference. Examples assume a **local daemon** at `http://127.0.0.1:10102`. ## At a Glance | Surface | Count | Notes | |---|---:|---| | **Tools** | **32** | 18 daemon RPC wrappers + 3 docs-index tools + 11 composites | | โ†ณ Daemon primitives | 18 | One per common daemon read method, plus local bech32 proof/address decode | | โ†ณ Docs primitives | 3 | Search, fetch-by-slug, enumerate across `derod` / `tela` / `hologram` / `deropay` | | โ†ณ Composite tools | 11 | Multi-step intent-shaped flows that fan out into primitives + docs and return a narrative with curated citations โ€” including a full TELA suite (inspect, read file content, discover apps by dURL) | | **Resources** | 4 | `server-info`, `safety-boundary`, `example-flows`, `composites` | | **Prompts** | 5 | Composite-first guided flows | | **Structured error codes** | 11 | Every error carries a `hint` and a `retryable` flag for agent self-correction | | **Transports** | 2 | Local **stdio** (default) + **streamable-HTTP** (self-hosted) โ€” both drive the same `buildServer()` factory, so the tool surface, response shapes, and error contract are identical | | **Bundled in the npm package** | 3 docs | `README.md`, `SKILL.md` (per-tool agent runbook), `POSITIONING.md` (audience boundary + comparison vs. ACP / Stripe / Crossmint / Skyfire) | Latest version, install commands, and per-release notes: see [npm](https://www.npmjs.com/package/dero-mcp-server) and the [GitHub releases](https://github.com/DHEBP/dero-mcp-server/releases). Tool identifiers, schemas, and behavior are semantically stable โ€” once a tool ships, its name, args, and response shape are preserved across minor and patch releases. Breaking changes only land in majors and are flagged in the release notes. ## Why This Matters AI assistants are powerful research and dev tools, but most blockchain integrations route through centralized APIs that log your queries. This server runs on **your machine**, talks to **your daemon** (or a public one you choose), and communicates with your AI over **local stdio**. No accounts, no analytics, no tracking โ€” just code you can audit. The bundled DERO documentation index (147 pages across `derod`, `tela`, `hologram`, and `deropay`) is shipped inside the package, so the AI can quote primary sources offline without a single network round-trip beyond the daemon you pointed it at. ## Install ```bash npm install -g dero-mcp-server ``` Requires Node.js 20+. Source code: [github.com/DHEBP/dero-mcp-server](https://github.com/DHEBP/dero-mcp-server) ยท npm: [dero-mcp-server](https://www.npmjs.com/package/dero-mcp-server) ## Run Your Own Node When `DERO_DAEMON_URL` is unset the server is **local-first**: it uses a local daemon at `127.0.0.1:10102` if one answers, and only falls back to a third-party public RPC when none is found. For real privacy, run your own daemon: ```bash ./derod --rpc-bind=127.0.0.1:10102 ``` Then point the MCP server at it via `DERO_DAEMON_URL` (see below). ## Configure Your MCP Client ### Claude Desktop Edit `claude_desktop_config.json`: | OS | Path | |----|------| | macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` | | Windows | `%APPDATA%\Claude\claude_desktop_config.json` | | Linux | `~/.config/claude/claude_desktop_config.json` | ```json { "mcpServers": { "dero": { "command": "dero-mcp-server", "env": { "DERO_DAEMON_URL": "http://127.0.0.1:10102" } } } } ``` Omit `env` to use the default public RPC. ### Cursor **Settings โ†’ MCP โ†’ Add Server** - Command: `dero-mcp-server` - Environment: `DERO_DAEMON_URL=http://127.0.0.1:10102` (optional) ### OpenCode ```bash opencode mcp add dero -- dero-mcp-server ``` Or with a local node: ```bash opencode mcp add dero -e DERO_DAEMON_URL=http://127.0.0.1:10102 -- dero-mcp-server ``` ### Continue ยท Cline ยท Zed ยท others Any MCP-compatible client works. The server uses **stdio** transport: ``` command: dero-mcp-server env: DERO_DAEMON_URL=http://127.0.0.1:10102 (optional) ``` Consult your client's MCP documentation for the exact config format. ### Inspect interactively To explore the full surface without committing to a client config, use the official MCP Inspector: ```bash npx @modelcontextprotocol/inspector dero-mcp-server ``` It opens a local web UI that lists every tool with its schema and annotations, lets you invoke any tool with form-filled args, and shows the structured response including `_meta.error` blocks. ## HTTP Mode (Self-Hosted) For clients that can't launch a local subprocess โ€” ChatGPT Custom Connectors, Cursor hosted mode, n8n / Zapier integrations โ€” run the server in streamable-HTTP mode and put it behind your own domain: ```bash DERO_MCP_AUTH_TOKEN=$(openssl rand -base64 48) \ dero-mcp-server --http # [dero-mcp-server] HTTP listening on 127.0.0.1:8787 (POST /mcp ยท GET /health) ``` | Variable | Default | Description | |---|---|---| | `DERO_MCP_HTTP` | unset | Set to `1` (or pass `--http`) to start in HTTP mode | | `DERO_MCP_HTTP_PORT` | `8787` | Listen port | | `DERO_MCP_HTTP_HOST` | `127.0.0.1` | Bind address. Use `0.0.0.0` to bind publicly (do not without auth + TLS upstream) | | `DERO_MCP_AUTH_TOKEN` | unset | If set, every `/mcp` request must carry `Authorization: Bearer `. Constant-time compared. | For a turnkey deploy with Caddy + auto-TLS + Docker Compose, see the [`deploy/`](https://github.com/DHEBP/dero-mcp-server/tree/main/deploy) reference in the repo. Anyone can fork and run their own `mcp.derod.org`-style instance. The stdio transport and the HTTP transport share the same `buildServer()` factory, so the tool surface, response shapes, and error codes are identical across both. ## What You Can Ask Once connected, talk to your AI naturally โ€” it will pick the right composite or primitive based on your intent: - *"Is the DERO daemon healthy and synced?"* โ†’ `diagnose_chain_health` - *"What does the contract at SCID `[โ€ฆ]` do?"* โ†’ `explain_smart_contract` - *"Look up transaction `[txid]` and tell me what it is."* โ†’ `trace_transaction_with_context` - *"Which DERO docs page should I read to deploy a TELA app?"* โ†’ `recommend_docs_path` - *"Estimate the gas cost to deploy this DVM contract."* โ†’ `estimate_deploy_cost` - *"Verify the claim that DERO's total supply has been correctly minted at the current tip."* โ†’ `audit_chain_artifact_claim` - *"Forge a payload proof showing any amount โ€” to see why 'Verified โœ“' on an explorer proves nothing."* โ†’ `dero_forge_demo_proof` - *"What's the SCID for `vault.tela`?"* โ†’ `dero_durl_to_scid` - *"What TELA apps exist on DERO? Show me a few."* โ†’ `dero_tela_list_apps` - *"Inspect the TELA app at SCID `[โ€ฆ]` โ€” what is it and what files does it have?"* โ†’ `tela_inspect` - *"Show me the actual HTML of that app's `index.html`."* โ†’ `tela_get_doc_content` - *"What's the current block height?"* โ†’ `dero_get_info` / `dero_get_height` - *"Show me the source code for contract `[SCID]`."* โ†’ `dero_get_sc` - *"Resolve the name `dero` to a wallet address."* โ†’ `dero_name_to_address` - *"Decode this bech32 proof string and tell me what it represents."* โ†’ `dero_decode_proof_string` ## Composite Tools Each composite replaces a multi-step primitive chain with a single call, returns a plain-language narrative summary, and stitches the most relevant bundled docs pages as `related_docs` citations. | Composite | Replaces | When to call | |---|---|---| | `diagnose_chain_health` | `Ping + GetInfo + GetHeight + GetTxPool` | Any "is the chain healthy / are we synced" question | | `explain_smart_contract` | `GetSC` + manual DVM-BASIC parsing + docs lookup | "What does this contract do" โ€” returns function surface + token/registry/minimal/generic classification + 1-4 curated DVM docs | | `recommend_docs_path` | 4ร— parallel `dero_docs_search` + manual ranking | Natural-language intent โ†’ ranked docs across all 4 DERO products; `product_hint` is a 1.5ร— score bias, not a filter | | `estimate_deploy_cost` | `GetGasEstimate` + manual surface extraction + manual gas interpretation | DVM deploy pre-flight โ€” returns gas estimate + plain-text breakdown + parsed function surface | | `trace_transaction_with_context` | `GetTransaction` + (for SC installs) `GetSC` + manual classification | "What is this tx" โ€” returns confirmation status, kind classification, ring stats, and parsed SC install surface inline | | `audit_chain_artifact_claim` | Multiple primitives + docs lookups + proof decode | End-to-end verifier for chain-related claims โ€” returns narrative + cited daemon state + flagged-artifact analysis + optional bech32 proof round-trips. Backbone of the adversarial-context defense layer | | `dero_forge_demo_proof` | `dero_get_transaction` + manual commitment math + bech32 encode | Forge a `deroproofโ€ฆ` display object for any tx / ring slot / amount โ€” the one-call reproduction of the [inflation-claim Part 3](/integrity/inflation-claim.md#part-3-forge-a-fake-proof-yourself) demo that **Verified โœ“ proves nothing**: payload proofs are user-forgeable. Also exercises SDK proof-decode paths. | | `tela_inspect` | `GetSC` + manual TELA-INDEX-1/DOC-1 schema parsing | "What is this TELA contract/app" โ€” auto-detects INDEX vs DOC, decodes the manifest (name, dURL, mods, the full DOC file list, version history, ratings) or the file metadata. Reads raw stored keys so large manifests aren't truncated | | `tela_get_doc_content` | `GetSC` + comment-block extraction (+ gzip decode) | "Show me this TELA file's content" โ€” extracts the actual on-chain HTML/CSS/JS from a TELA-DOC-1, transparently gunzipping `.gz` files to plaintext | | `dero_durl_to_scid` | a separate Gnomon indexer | "What's the SCID for `vault.tela`" โ€” resolves a TELA dURL to its on-chain SCID(s) by discovering apps in-process (no external indexer). Non-unique dURLs return the newest as primary and disclose other claimants | | `dero_tela_list_apps` | a separate Gnomon indexer | "What TELA apps exist" โ€” lists/searches discovered TELA apps (dURL, name, SCID, file count) with transparent scan-coverage metadata | Each composite is fully documented in [`docs/composites.md`](https://github.com/DHEBP/dero-mcp-server/blob/main/docs/composites.md) (design contract, accepted/rejected designs, failure modes), and every composite ships with a green flow test in CI that runs against a live public daemon. > [!NOTE] > **Why composites matter for agents.** A generic JSON-RPC client can chain primitives, but it cannot stitch the right docs context or classify failure modes for free. Composites are the wedge: they deliver agent-ready answers from the canonical DERO data sources in one call. ## Primitive Tools The 21 primitives map 1:1 onto daemon RPC methods (18) plus the bundled docs index (3). Use them when a composite is unavailable or you need raw data. ### Daemon RPC | Tool | RPC Method | Purpose | |------|------------|---------| | `dero_daemon_ping` | `DERO.Ping` | Liveness check | | `dero_daemon_echo` | `DERO.Echo` | Roundtrip string echo | | `dero_get_info` | `DERO.GetInfo` | Network height, difficulty, version, hashrate, testnet flag | | `dero_get_height` | `DERO.GetHeight` | Height, stableheight, topoheight | | `dero_get_block_count` | `DERO.GetBlockCount` | Total block count | | `dero_get_block` | `DERO.GetBlock` | Full block by hash or height | | `dero_get_block_header_by_hash` | `DERO.GetBlockHeaderByHash` | Block header by hash | | `dero_get_block_header_by_topo_height` | `DERO.GetBlockHeaderByTopoHeight` | Block header by topoheight | | `dero_get_last_block_header` | `DERO.GetLastBlockHeader` | Tip block header | | `dero_get_block_template` | `DERO.GetBlockTemplate` | Mining block template | | `dero_get_transaction` | `DERO.GetTransaction` | Transaction record by hash | | `dero_get_tx_pool` | `DERO.GetTxPool` | Mempool transaction hashes | | `dero_get_sc` | `DERO.GetSC` | Smart contract code, variables, balances | | `dero_get_gas_estimate` | `DERO.GetGasEstimate` | Daemon-side gas estimate for a contract source or call | | `dero_get_encrypted_balance` | `DERO.GetEncryptedBalance` | Encrypted balance for an address | | `dero_get_random_address` | `DERO.GetRandomAddress` | Random registered wallet addresses | | `dero_name_to_address` | `DERO.NameToAddress` | Resolve a registered name to its address | | `dero_decode_proof_string` | _(local โ€” no RPC)_ | Decode a DERO bech32 proof/address string locally. Powers the adversarial-context defense layer and the demo-proof composite | ### Bundled docs index | Tool | Purpose | |------|---------| | `dero_docs_list` | Enumerate available doc pages across `derod`, `tela`, `hologram`, `deropay` | | `dero_docs_search` | Full-text search across the bundled docs index โ€” in-process, no network round-trip | | `dero_docs_get_page` | Fetch a single doc page by slug with full plain-text content and headings | ## Resources and Prompts Beyond tools, the server exposes 4 **resources** and 5 **prompts** so MCP-aware clients can surface them in their UI: ### Resources | URI | Content | |-----|---------| | `dero://mcp/server-info` | Server metadata, tool list, resource list, prompt names, daemon endpoint | | `dero://mcp/safety-boundary` | Read-only posture and excluded method list (transfer, scinvoke, etc.) | | `dero://mcp/example-flows` | Composite-first agent flow recipes for common DERO investigations | | `dero://mcp/composites` | Structured catalog of all 11 composites โ€” what each replaces, when to call it, what it returns, and which `_meta.error` codes it can emit | ### Prompts | Prompt | What it scripts | |--------|----------------| | `network_health_check` | Drives `diagnose_chain_health` with optional `reference_topoheight` | | `inspect_smart_contract` | Drives `explain_smart_contract` for any SCID | | `trace_transaction` | Drives `trace_transaction_with_context` for any tx hash | | `find_dero_docs_for_intent` | Drives `recommend_docs_path` with a natural-language intent + optional `product_hint` | | `estimate_deploy_for_contract` | Drives `estimate_deploy_cost` with DVM-BASIC source | ## Structured Errors Every tool wraps failures in a structured `_meta.error` block so agents can react programmatically instead of parsing error strings: | Code | Emitted by | Meaning | Retryable | |------|------------|---------|:---------:| | `INVALID_INPUT` | `estimate_deploy_cost` + others | Tool input shape is wrong (wraps daemon `-32098` for DVM compile errors); raw message preserved in `_meta.error.raw` | no โ€” read the hint | | `INVALID_BECH32` | `dero_decode_proof_string`, audit + forge composites | Bech32 proof/address string failed to decode | no โ€” re-check input string | | `NO_DOCS_MATCH` | `recommend_docs_path` | Intent matched zero pages across all 4 products | no โ€” rephrase intent (drop verbs) | | `DOC_NOT_FOUND` | `dero_docs_get_page` | Slug doesn't exist in the bundled index | no โ€” use `dero_docs_search` to find valid slugs | | `TX_NOT_FOUND` | `trace_transaction_with_context` | Daemon returned an empty record for the hash | yes โ€” verify hash + network; retryable if freshly broadcast | | `RPC_UNREACHABLE` | All daemon tools | Daemon not reachable on `DERO_DAEMON_URL` | yes โ€” check daemon + run `npm run doctor` | | `RPC_INVALID_PARAMS` | Most daemon tools | Daemon rejected the request shape | no โ€” check arg names and types | | `RPC_METHOD_NOT_FOUND` | All daemon tools | Daemon outdated or not Stargate | no โ€” surface to user; they need to upgrade | | `RPC_HTTP_ERROR` | All daemon tools | HTTP-level error from the daemon | yes โ€” check `DERO_DAEMON_URL` | | `DOCS_UNAVAILABLE` | All docs tools | Bundled docs index missing from the install | no โ€” reinstall `dero-mcp-server` | | `TOOL_EXECUTION_ERROR` | All tools | Catch-all unexpected error | yes โ€” retry once, then inspect daemon logs | Every error code carries a `hint` string with actionable next steps so the agent can recover or explain the failure cleanly to the user. ## Read-Only by Design Every one of the 32 tools carries the MCP read-only annotation block: ```json { "readOnlyHint": true, "destructiveHint": false, "idempotentHint": false, "openWorldHint": false } ``` This lets MCP hosts safely auto-approve any tool call from this server without prompting on every read. The server **cannot**: - Send transactions - Transfer funds - Invoke smart contracts (only **estimate** deploy cost via `estimate_deploy_cost` โ€” nothing is submitted to chain) - Submit blocks - Hold wallet keys or talk to wallet RPC Wallet RPC methods (`transfer`, `scinvoke`, `DERO.SendRawTransaction`, `DERO.SubmitBlock`) are explicitly excluded. The full read-only posture, the six AND-gated conditions that would be required to expand the boundary, and the rationale for each are documented in [`docs/decision-boundary.md`](https://github.com/DHEBP/dero-mcp-server/blob/main/docs/decision-boundary.md). If you need write capabilities in the future, they will be gated behind explicit flags **and** a separate wallet URL **and** a distinct annotation block (`readOnlyHint: false`) **and** documented escalation โ€” never enabled by default. ## Environment | Variable | Default | Description | |----------|---------|-------------| | `DERO_DAEMON_URL` | `http://82.65.143.182:10102` | Daemon base URL. Set to `http://127.0.0.1:10102` for a local node. | | `DERO_DOCS_ROOT` | _(unset; uses bundled index)_ | Optional dev override pointing at a local docs source tree. Production deployments should leave this unset to use the bundled index. | | `DERO_MCP_HTTP` | unset | Set to `1` (or pass `--http`) to start in streamable-HTTP mode instead of stdio. | | `DERO_MCP_HTTP_PORT` | `8787` | HTTP listen port when running in HTTP mode. | | `DERO_MCP_HTTP_HOST` | `127.0.0.1` | HTTP bind address. Use `0.0.0.0` to bind publicly (only behind auth + TLS upstream). | | `DERO_MCP_AUTH_TOKEN` | unset | Bearer token for HTTP `/mcp` requests. If set, every request must carry `Authorization: Bearer `. Constant-time compared. | ## Verify, Don't Trust - [Source code on GitHub](https://github.com/DHEBP/dero-mcp-server) โ€” composite design contract in `docs/composites.md`, read-only posture in `docs/decision-boundary.md`, agent-ready evidence in `docs/mcp-agent-ready-evidence.md` - **Bundled with the npm package:** `SKILL.md` is the per-tool agent operating manual (composite-first rule, port reference, structured error contract, workflow recipes, safety rules); `POSITIONING.md` covers who this server is for vs. who it isn't, with a comparison vs. ACP / Stripe / Crossmint / Skyfire - Agent-discovery surfaces at [`/.well-known/agent-card.json`](/.well-known/agent-card.json) (A2A v0.2-draft descriptor for the broader agent ecosystem) and [`/.well-known/mcp-server-card.json`](/.well-known/mcp-server-card.json) (MCP-specific descriptor) - [Package on npm](https://www.npmjs.com/package/dero-mcp-server) - [Listed in the official MCP registry](https://registry.modelcontextprotocol.io/) as `io.github.DHEBP/dero-mcp-server` - CI runs full smoke probes, composite flow tests, primitive flow tests, description / citation drift guards, and HTTP transport smoke tests on every push - MIT licensed โ€” fork it, audit it, improve it ## See Also - [DERO Daemon RPC API](/rpc-api/daemon-rpc-api.md) โ€” full RPC reference for the methods the primitives wrap - [Running a DERO Node](/basics/running-a-node.md) โ€” set up your own daemon - [Smart Contract Fundamentals](/dvm/smart-contract-fundamentals.md) โ€” DVM concepts the composites cite - [XSWD](/tools/xswd.md) โ€” browser wallet integration (for write flows the MCP server intentionally excludes) - [`SKILL.md`](https://derod.org/SKILL.md) โ€” agent operating manual served at the docs origin (mirror of the npm-bundled file) - [`agents.md`](https://derod.org/agents.md) โ€” human-and-LLM-readable operating runbook for the whole DERO docs surface - [`llms.txt`](https://derod.org/llms.txt) โ€” curated agent map of the DERO docs corpus --- --- title: "TELA Platform: Private Web3 Framework | DERO Blockchain" description: "TELA is DERO's decentralized web framework for building privacy-focused dApps that run entirely on-chain with encrypted storage and local execution." keywords: ["TELA", "TELA platform", "Web3 framework", "decentralized apps", "on-chain web", "private dApps", "DERO TELA", "blockchain web", "local execution", "encrypted storage"] date: "2025-10-19" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/tela.jpeg" slug: "tela" canonicalUrl: "https://derod.org/tools/tela" tags: ["tools", "TELA", "Web3", "dApps", "framework"] --- # TELA Platform ![What is TELA](/assets/what-is-TELA.png) **TELA** is a revolutionary private web3 platform built on DERO blockchain, enabling truly private and decentralized web applications that run entirely on-chain. > [!NOTE] > **Full Documentation:** [tela.derod.org](https://tela.derod.org) --- ## What is TELA? TELA enables developers to build web applications where: - ๐Ÿ“ฆ **Code stored on-chain** - In DERO smart contracts - ๐Ÿ”’ **Data encrypted** - User data stays private - ๐Ÿ’ป **Runs locally** - Executes in Engram browser - ๐ŸŒ **No servers** - Truly decentralized **Think:** Decentralized websites that can't be censored, modified, or taken down. --- ## Key Features | Feature | Description | |---------|-------------| | **On-Chain Storage** | Entire app (HTML/CSS/JS) stored in smart contracts | | **Local Execution** | Runs in user's Engram wallet, not on servers | | **Privacy-First** | User data encrypted, no tracking | | **Censorship-Resistant** | Can't be taken down or blocked | | **DERO Integration** | Native access to blockchain, wallets, tokens | --- ## TELA vs Traditional Web | Aspect | Traditional Web | TELA | |--------|----------------|------| | **Hosting** | Centralized servers | DERO blockchain | | **Storage** | Server databases | Smart contracts | | **Execution** | Server-side | Local (Engram) | | **Privacy** | Tracked, logged | Encrypted, private | | **Censorship** | Can be blocked | Unstoppable | | **Cost** | Monthly hosting fees | One-time blockchain fee | --- ## Use Cases **TELA enables:** - ๐ŸŽฎ Decentralized games - ๐Ÿ’ฌ Private messaging apps - ๐Ÿ“Š Data visualization tools - ๐ŸŽจ NFT galleries - ๐Ÿ—ณ๏ธ Voting systems - ๐Ÿ“ Collaborative tools All running on-chain with complete privacy! --- ## Access TELA Docs > [!NOTE] > **Complete TELA Documentation:** [tela.derod.org](https://tela.derod.org) > > Includes: > - Building TELA apps > - TELA protocol > - API reference > - Example applications > - Deployment guides --- ## Learn More **TELA Documentation:** - ๐ŸŒ [tela.derod.org](https://tela.derod.org) - Complete TELA documentation - ๐Ÿ“– [TELA Development Guide](https://tela.derod.org/tela-development-guide) - Building with TELA - ๐Ÿ”ง [TELA API Reference](https://tela.derod.org/api-reference/complete-api-guide) - Technical API reference - ๐ŸŽ“ [First App Tutorial](https://tela.derod.org/tutorials/first-app) - Getting started with TELA - ๐Ÿ“ [Templates](https://tela.derod.org/templates/overview) - Ready-to-use TELA app templates **DERO Integration:** - [Engram](/engram.md) - TELA browser/wallet - [Private Smart Contracts](/privacy/private-smart-contracts.md) - Backend for TELA apps - [DVM](/features/dvm.md) - Smart contract execution --- --- title: "XSWD WebSocket Layer | DERO Blockchain" description: "The XSWD protocol revolutionizes the interaction between applications and user wallets through WebSocket connections, providing secure dApp authentication." keywords: ["XSWD", "WebSocket protocol", "security", "usability", "dApps", "wallet integration", "DERO protocol", "secure connections", "dApp security"] date: "2024-08-26" lastUpdated: "2025-10-19" authors: ["DHEBP"] image: "/assets/xswd.jpeg" slug: "xswd" canonicalUrl: "https://derod.org/tools/xswd" tags: ["tools", "XSWD", "WebSocket", "dApps", "wallet-integration"] --- # Secure Web Sockets ![XSWD](/assets/xswd.jpeg) ## What is XSWD? XSWD is a groundbreaking application layer protocol designed to elevate security and usability in the interaction between applications and user wallets. The XSWD protocol facilitates secure interaction with dApps from any website by establishing WebSocket connections. WebSockets enable real-time, bidirectional communication between web clients and servers, for direct communication. In any case, the user can easily prevent any unauthorized access. Without this protocol, you would have to authorize full access to your wallet for interacting with any third-party application. ## Features and Benefits - **Elimination of RPC Bridge Dependency**: XSWD eliminates the need for the RPC bridge browser extension. - **On-Demand Communication**: XSWD adopts a novel paradigm where communication between dApps and wallets occurs on a per-request basis. - **Secure dApp Interaction:** XSWD ensures safe connections and authentication with dApps via WebSocket. - **Flexible Permissions:** Users can opt to deny, allow (one-time or always), or permanently reject requests from dApps, providing control over data access. - **Ease of Integration:** Manage integration effortlessly through CLI wallet commands. Toggle the XSWD Server and manage dApp permissions. - **Proxy for Daemon Requests:** XSWD acts as a proxy, offering a comprehensive API for developers to integrate DERO into their services or dApps. ## Permissions The permissions are set based on the RPC method requested and are the following: - **ask**: The application must ask each time the permission to the user when a request is made. - **accept_always**: The application is allowed to make the request without asking the user each time. - **deny_always**: The application is not allowed to make the request and the user will not be asked again. Request will be always denied until changed. The permissions are **not** persisted in the wallet and are only valid for the current session. For persistance, the application must store the permissions set by the user and send it back in the ApplicationData message if allowed. --- ## Using XSWD > [!NOTE] > **Implementation Guides:** > - [Connect Wallet to Engram](/engram/wallet-integration.md) - Step-by-step Engram wallet connection > - [Complete XSWD API](https://tela.derod.org/xswd/overview) - Full protocol documentation (TELA docs) > - [TELA Development Guide](https://tela.derod.org/tela-development-guide) - Using XSWD in TELA apps > - [API Reference](https://tela.derod.org/api-reference/complete-api-guide) - XSWD RPC methods **Where XSWD is Used:** - **Engram Wallet** - Desktop wallet with XSWD support - **TELA Applications** - Web apps connect via XSWD for blockchain access - **TELA-CLI** - Command-line TELA development with XSWD integration - **Web-based dApps** - Browser apps using WebSocket connections **Official Implementation:** - Source code: [github.com/deroproject/derohe/tree/dev/walletapi/xswd](https://github.com/deroproject/derohe/tree/dev/walletapi/xswd) - Part of DERO wallet API --- ## Related Pages **Getting Started:** - [Engram Wallet](/engram/index.md) - XSWD-compatible wallet - [Engram Wallet Integration](/engram/wallet-integration.md) - How to connect your wallet - [TELA Platform](/tools/tela.md) - Build apps using XSWD **For Developers:** - [Wallet RPC API](/rpc-api/wallet-rpc-api.md) - Wallet methods available via XSWD - [Daemon RPC API](/rpc-api/daemon-rpc-api.md) - Network methods available via XSWD