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 informationThe 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 invalidSource: 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
| Input | Binary String | First Char | Result |
|---|---|---|---|
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 networkSource: 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.goExpected 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
| Threat | Layer | How It's Blocked |
|---|---|---|
| Negative amounts | Layer 1 | '-' character detected in bit string |
| Overflow amounts | Layer 2 | Range proof validates the 128-bit combined value with 64-bit bounds |
| Forged proofs | Layer 3 | Inner product verification fails |
| Partial forgery | All | All layers must pass |
Attack Impossibility
To create a negative transfer, attacker would need to:
- Create negative BigInt value → Layer 1 blocks (detects '-')
- Somehow bypass Layer 1 → Layer 2 blocks (invalid commitments)
- Somehow bypass Layers 1 & 2 → Layer 3 blocks (inner product mismatch)
- 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
| Layer | What It Checks | Why It's Sufficient |
|---|---|---|
| Layer 1 | Bit string format | Go stdlib guarantee |
| Layer 2 | Mathematical range | Bulletproof security |
| Layer 3 | Cryptographic integrity | Recursive 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:
- Negative Transfer Protection - Detailed impossibility proof
- Transaction Proofs - Six sigma proof system
- Proof Verification Flow - Complete verification process
Privacy Suite:
- Bulletproofs - Zero-knowledge range proofs
- Homomorphic Encryption - Encrypted operations