Protocol Integrity
Balance Mechanics

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               │
└──────────────────────────────────┴──────────────────────────────────┘

From Source Code (cryptography/crypto/algebra_elgamal.go):

type ElGamal struct {
    G          *bn256.G1   // Generator point
    Randomness *big.Int    // Blinding factor (used during construction)
    Left       *bn256.G1   // L = amount×G + r×P (33 bytes compressed)
    Right      *bn256.G1   // R = r×G (33 bytes compressed)
}
 
// Only Left and Right are serialized (66 bytes)
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 (generator) and Randomness (blinding factor) fields used during construction, but only Left and Right are serialized to the 66-byte on-chain representation.

What Each Component Represents

ComponentFormulaPurpose
Left (L)amount×G + r×PEncrypted amount + randomness
Right (R)r×GRandomness commitment (for decryption)

Where:

  • amount = The actual balance (hidden)
  • G = Generator point (public constant)
  • r = Random blinding factor (secret)
  • P = Account's public key

Zero Balance Initialization

The Genesis Rule

From Source Code (blockchain/transaction_execute.go:189-194):

// 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 BlockInitial BalanceReason
< 144,000200 atomic unitsEarly adoption period
≥ 144,0000 DEROStandard 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:

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:

The Math:

E(balance) - E(amount) = (L_balance - L_amount, R_balance - R_amount)
                       = E(balance - amount)

Source: cryptography/crypto/algebra_elgamal.go:69 - ElGamal operations


What Balance Changes Mean

When Balance Changes

ScenarioBalance Changes?Reason
Send DEROYesSubtracted from your balance
Receive DEROYesAdded to your balance
Ring member (decoy)YesParticipates in ring signature
No activityNoBalance 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 for details.

From Source Code (walletapi/daemon_communication.go:886-889):

// When address is a ring member:
changes := crypto.ConstructElGamal(tx.Payloads[t].Statement.C[j], tx.Payloads[t].Statement.D)
changed_balance_e := previous_balance_e_tx.Add(changes)
// Balance changes even if address is just a decoy!

Balance Query Process

How to Query Balance

Query Encrypted Balance (Public)

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:

{
  "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

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

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

PropertyHow It's Achieved
Balance confidentialityElGamal encryption
Balance integrityCommitment binding
ConservationHomomorphic verification
Non-negative balancesRange proofs

What's Visible

InformationVisible To
Encrypted balance (66 bytes)Anyone
That balance changedAnyone
Actual balance valueOnly owner
Transaction amountsOnly 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

ObservationWhat It MeansWhat It Doesn't Mean
Balance unchangedAddress not involved in ANY transaction-
Balance changedAddress participated in some transaction≠ Address was sender
66 bytes differentSome 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:

Privacy Suite:

Technical Reference: