Protocol Integrity
Range Proof Integrity

Range Proof Integrity: Triple-Layer Defense

🛡️

Triple Protection: Three independent layers ensure amounts are always valid. Layer 1 catches issues at bit decomposition. Layer 2 validates the range. Layer 3 provides a cryptographic fail-safe. All three must pass.

What Problem Does Range Proof Integrity Solve?

The Challenge:

DERO needs to verify:
  ✓ Amount is positive (not negative)
  ✓ Amount is reasonable (not 999 trillion)
  ✓ Proof is mathematically valid
  
But WITHOUT revealing:
  ✗ The actual amount
  ✗ Any bits of the amount
  ✗ Any private information

The Solution: Triple-Layer Defense

  • ✅ Layer 1: Bit decomposition catches negatives at string level
  • ✅ Layer 2: Range proof (A_t) validates mathematical range
  • ✅ Layer 3: Inner product proof provides cryptographic guarantee

The Three Layers


Layer 1: Bit Decomposition

How It Works

Layer 1 converts the 128-bit combined value (transfer + balance) into binary and processes each bit. The key protection: Go's BigInt.Text(2) always prepends a - character for negative values, which breaks the bit processing loop that expects only '0' or '1'.

Valid amount (100):    "1100100"       → All bits valid ✓
Negative amount (-100): "-1100100"     → '-' breaks processing ✗
                         ↑ First char is invalid

Source: cryptography/crypto/proof_generate.go:468-487

📐

Full Technical Details: For the complete code walkthrough, Go stdlib guarantees, and verification tests, see Negative Transfer Protection.

Why Negatives Fail

InputBinary StringFirst CharResult
100"1100100"'1' (ASCII 49)✅ Valid bit
-100"-1100100"'-' (ASCII 45)❌ Invalid - proof fails

The bit processing loop expects only '0' (48) or '1' (49). The minus sign character '-' (45) creates a malformed bit vector, causing downstream proof verification to fail.


The 128-Bit Combined Range Proof

📐

Dual Validation: DERO's range proof validates TWO values simultaneously in a single 128-bit proof: the transfer amount (lower 64 bits) AND the remaining balance (upper 64 bits). This proves both values are non-negative in one efficient proof.

From Source Code (proof_generate.go:471):

// Combine transfer amount + remaining balance into single 128-bit value
number := btransfer.Add(btransfer, bdiff.Lsh(bdiff, 64))

What This Means:

128-bit value structure:
┌────────────────────────────────────────────────────────────────┐
│  Upper 64 bits: Remaining Balance  │  Lower 64 bits: Transfer  │
└────────────────────────────────────────────────────────────────┘

Both 64-bit components must be in range [0, 2^64) for the proof to be valid.
A negative transfer OR negative remaining balance makes the combined 128-bit proof invalid.

Layer 2: Range Proof (A_t)

What A_t Validates

A_t Range Proof verifies:
  ✓ Transfer amount is in [0, 2^64) (lower 64 bits)
  ✓ Remaining balance is in [0, 2^64) (upper 64 bits)
  ✓ Bit commitments are valid
  ✓ All 128 bits are 0 or 1 (binary)

How It Works

Mathematical Structure:

If Layer 1 Fails

If bit string contains '-':
  → Cannot create valid bit commitments
  → Commitment to '-' is undefined
  → A_t proof is invalid and fails verification
  → Transaction is rejected by the network

Source: cryptography/crypto/proof_generate.go - A_t generation


Layer 3: Inner Product Proof

The Cryptographic Fail-Safe

Purpose: Ensures complete integrity across all proof components using recursive verification.

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

// Inner product proof verifies:
// - Bit vectors (aL, aR) match commitments
// - Final inner product equals committed value
// - All recursive steps are cryptographically consistent
 
// Verification check
if P_calculated.String() != P.String() {
    // Verification fails
    // Transaction rejected
    return false
}

The Recursive Algorithm

At each step:

  • Create commitments L and R
  • Derive challenge from hash
  • Fold vectors in half
  • Repeat until single element

Why It's a Fail-Safe

Even if Layers 1 and 2 were somehow bypassed:

Invalid bit vector (e.g., contains '-' representation):
  → Creates inconsistent commitments
  → Recursive verification detects mismatch
  → Final inner product ≠ committed value
  → Proof FAILS

The inner product proof is the cryptographic guarantee
that all previous steps were honest.

The Complete Protection Chain


Verification: How to Confirm

Method 1: Test Go Behavior (1 minute)

cat <<'EOF' > /tmp/bit_test.go
package main
 
import (
    "fmt"
    "math/big"
)
 
func main() {
    n := new(big.Int).SetInt64(-2200000)
    fmt.Printf("Binary: %s\n", n.Text(2))
    fmt.Printf("First char: %q (ASCII %d)\n", n.Text(2)[0], n.Text(2)[0])
}
EOF
 
go run /tmp/bit_test.go

Expected Output:

Binary: -1000011001000111000000
First char: '-' (ASCII 45)

Method 2: Review Source Code

# View the critical code
git clone https://github.com/deroproject/derohe.git
cd derohe
cat cryptography/crypto/proof_generate.go | sed -n '473,487p'

Look for:

  • Line 473: number.Text(2) call
  • Line 476: Comment "convert the amount to make sure it cannot be negative"
  • Lines 479-487: Bit processing loop expecting '0' and '1'

Security Guarantees

What's Protected

ThreatLayerHow It's Blocked
Negative amountsLayer 1'-' character detected in bit string
Overflow amountsLayer 2Range proof validates the 128-bit combined value with 64-bit bounds
Forged proofsLayer 3Inner product verification fails
Partial forgeryAllAll layers must pass

Attack Impossibility

To create a negative transfer, attacker would need to:

  1. Create negative BigInt value → Layer 1 blocks (detects '-')
  2. Somehow bypass Layer 1 → Layer 2 blocks (invalid commitments)
  3. Somehow bypass Layers 1 & 2 → Layer 3 blocks (inner product mismatch)
  4. Somehow bypass all layers → Network consensus blocks (all nodes verify)

Each layer is independently sufficient to prevent the attack.


Key Takeaways

The Triple-Layer Guarantee

LayerWhat It ChecksWhy It's Sufficient
Layer 1Bit string formatGo stdlib guarantee
Layer 2Mathematical rangeBulletproof security
Layer 3Cryptographic integrityRecursive verification

Why This Matters

📐

Defense in Depth: Even if one layer had a theoretical weakness, the other layers provide independent protection. This is not "belt and suspenders" - it's three completely independent mathematical guarantees.

🔒

Mathematical Certainty: Negative transfers are not "difficult" to create - they are mathematically impossible. The bit decomposition mechanism makes it as impossible as dividing by zero.


Related Pages

Security Suite:

Privacy Suite: