Skip to content

Commit f45c008

Browse files
committed
docs: add comprehensive documentation for RedBlackTreeWithResize feature
- Update README with RedBlackTreeWithResizeKV usage examples and documentation - Add enhanced operations section showing resize functionality - Document storage capacity management and pre-allocation benefits - Expand test coverage section for all resize-related test suites - Add specific use cases and guidance for when to use resize features - Fix contract name in RedBlackTreeWithResize.sol test file - Add storage slot cleanup logic in RedBlackTreeWithResizeLib resize function
1 parent 4be4fe6 commit f45c008

File tree

3 files changed

+106
-11
lines changed

3 files changed

+106
-11
lines changed

README.md

Lines changed: 96 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ The Red-Black Tree implementation is based on [Solady's RedBlackTreeLib](https:/
1414
- **Complex Value Support**: Stores `ValueLib.Value` structs containing any size of data. In this example, it shows 6 slots.
1515
- **Red-Black Tree Properties**: Maintains balanced tree structure ensuring O(log n) operations
1616
- **Zero Value Protection**: Prevents insertion of zero keys to maintain tree integrity
17+
- **Dynamic Resizing**: Pre-allocate storage capacity to optimize gas costs for future insertions (available in `RedBlackTreeWithResizeLib`)
1718

1819
### Gas Performance
1920

@@ -38,15 +39,19 @@ The Red-Black Tree implementation shows **90% gas reduction** for hot insertions
3839

3940
```
4041
src/
41-
├── RedBlackTreeKV.sol # Main KV store implementation
42-
├── MappingKV.sol # Traditional mapping implementation for comparison
42+
├── RedBlackTreeKV.sol # Main KV store implementation
43+
├── RedBlackTreeWithResizeKV.sol # Enhanced KV store with resize capabilities
44+
├── MappingKV.sol # Traditional mapping implementation for comparison
4345
└── lib/
44-
├── RedBlackTreeLib.sol # Red-Black Tree data structure library
45-
└── Value.sol # Value struct definition
46+
├── RedBlackTreeLib.sol # Red-Black Tree data structure library
47+
├── RedBlackTreeWithResizeLib.sol # Enhanced Red-Black Tree with resize capabilities
48+
└── Value.sol # Value struct definition
4649
4750
test/
48-
├── RedBlackTreeKV.t.sol # Comprehensive unit tests
49-
└── RedBlackTreeKVGas.t.sol # Gas benchmark tests
51+
├── RedBlackTreeKV.t.sol # Comprehensive unit tests
52+
├── RedBlackTreeWithResizeKV.t.sol # Tests for resize-enabled KV store
53+
├── RedBlackTreeWithResize.sol # Red-Black Tree library tests with resize functionality
54+
└── RedBlackTreeKVGas.t.sol # Gas benchmark tests
5055
```
5156

5257
## Value Structure
@@ -95,6 +100,54 @@ kv.deleteValue(1);
95100
uint256[] memory keys = kv.values();
96101
```
97102

103+
### Enhanced Operations with Resize
104+
105+
```solidity
106+
RedBlackTreeWithResizeKV kvWithResize = new RedBlackTreeWithResizeKV();
107+
108+
// Pre-allocate storage for 1000 elements to optimize gas costs
109+
kvWithResize.resize(1000);
110+
111+
// Check current storage metrics
112+
uint256 capacity = kvWithResize.getStorageSize(); // Returns 1000
113+
uint256 size = kvWithResize.getSize(); // Returns current number of elements
114+
115+
// Set values with optimized gas costs
116+
kvWithResize.setValue(1, value);
117+
kvWithResize.setValue(2, anotherValue);
118+
119+
// All other operations work the same
120+
ValueLib.Value memory retrieved = kvWithResize.getValue(1);
121+
kvWithResize.deleteValue(1);
122+
uint256[] memory keys = kvWithResize.values();
123+
```
124+
125+
### WithResize Feature
126+
127+
The `RedBlackTreeWithResizeLib` provides enhanced functionality for pre-allocating storage capacity to optimize gas costs:
128+
129+
```solidity
130+
import "./lib/RedBlackTreeWithResizeLib.sol";
131+
132+
RedBlackTreeWithResizeLib.Tree tree;
133+
134+
// Pre-allocate storage for 1000 elements to save gas on future insertions
135+
RedBlackTreeWithResizeLib.resize(tree, 1000);
136+
137+
// Check current storage capacity
138+
uint256 capacity = RedBlackTreeWithResizeLib.storageSize(tree);
139+
140+
// Insert values with optimized gas costs
141+
RedBlackTreeWithResizeLib.insert(tree, 42);
142+
```
143+
144+
#### Resize Benefits
145+
146+
- **Pre-allocation**: Reserve storage slots in advance to avoid costly allocations during insertion
147+
- **Gas Optimization**: Significantly reduces gas costs for insertions when capacity is pre-allocated
148+
- **Flexible Sizing**: Dynamically adjust storage capacity based on expected usage patterns
149+
- **Auto-increment**: Storage capacity automatically increases when inserting beyond current capacity
150+
98151
### Constraints
99152

100153
- **No Zero Keys**: Keys cannot be 0 (will revert with `ValueIsEmpty()`)
@@ -117,6 +170,11 @@ forge test
117170

118171
# Run unit tests only
119172
forge test --match-contract RedBlackTreeKVTest
173+
forge test --match-contract RedBlackTreeWithResizeKVTest
174+
175+
# Run resize library tests
176+
forge test --match-contract RedBlackTreeLibTest
177+
forge test --match-contract RedBlackTreeWithResizeLibTest
120178

121179
# Run gas benchmarks
122180
forge test --match-contract MappingGasTest -vv
@@ -126,6 +184,8 @@ forge test --match-contract MappingGasTest -vv
126184

127185
The test suite includes:
128186

187+
**RedBlackTreeKV Tests:**
188+
129189
- ✅ Basic CRUD operations
130190
- ✅ Edge cases (zero keys, max values)
131191
- ✅ Multiple value operations
@@ -134,14 +194,40 @@ The test suite includes:
134194
- ✅ Fuzz testing with random inputs
135195
- ✅ Gas consumption benchmarks
136196

197+
**RedBlackTreeWithResizeKV Tests:**
198+
199+
- ✅ All basic KV operations with resize functionality
200+
- ✅ Storage capacity management and pre-allocation
201+
- ✅ Resize operations (expand, shrink, same capacity)
202+
- ✅ Data preservation during resize operations
203+
- ✅ Error handling for invalid resize operations
204+
- ✅ Resize with mixed insert/delete operations
205+
- ✅ Fuzz testing for resize capacity variations
206+
207+
**RedBlackTreeWithResizeLib Tests:**
208+
209+
- ✅ Core Red-Black Tree operations with resize support
210+
- ✅ Storage size tracking and capacity management
211+
- ✅ Tree balancing with dynamic storage allocation
212+
- ✅ Error cases for tree size limits and invalid operations
213+
137214
## Use Cases
138215

139216
This implementation is ideal for:
140217

141-
- **Order Books**: Frequent order insertions and cancellations
142-
- **Gaming**: Player inventory systems with item trading
143-
- **DeFi Protocols**: Position management with frequent updates
144-
- **NFT Marketplaces**: Listing and delisting operations
218+
- **Order Books**: Frequent order insertions and cancellations with predictable volume patterns
219+
- **Gaming**: Player inventory systems with item trading and known capacity requirements
220+
- **DeFi Protocols**: Position management with frequent updates and batch operations
221+
- **NFT Marketplaces**: Listing and delisting operations with seasonal volume spikes
222+
- **Data Analytics**: Time-series data storage with known dataset sizes
223+
- **Batch Processing**: Systems that process large batches of data with predictable patterns
224+
225+
**When to use RedBlackTreeWithResizeKV:**
226+
227+
- You know the approximate maximum number of elements in advance
228+
- You need to optimize for gas costs during high-frequency operations
229+
- Your application has predictable usage patterns or batch processing requirements
230+
- You want to avoid gas spikes during storage allocation
145231

146232
## License
147233

src/lib/RedBlackTreeWithResizeLib.sol

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ library RedBlackTreeWithResizeLib {
136136
/// Returns a non-zero error code upon failure instead of reverting.
137137
function tryResize(Tree storage tree, uint256 newCapacity) internal returns (uint256 err) {
138138
uint256 currentSize = size(tree);
139+
uint256 oldCapacity = storageSize(tree);
139140
if (newCapacity > _BITMASK_KEY) return ERROR_TREE_IS_FULL;
140141
if (newCapacity < currentSize) return ERROR_INVALID_STORAGE_SIZE;
141142

@@ -158,6 +159,14 @@ library RedBlackTreeWithResizeLib {
158159
sstore(or(nodes, index), 1)
159160
sstore(or(_BIT_FULL_VALUE_SLOT, or(nodes, index)), 1)
160161
}
162+
163+
// Release storage slots for smaller capacity
164+
start := add(newCapacity, 1)
165+
end := oldCapacity
166+
for { let index := start } iszero(gt(index, end)) { index := add(index, 1) } {
167+
sstore(or(nodes, index), 0)
168+
sstore(or(_BIT_FULL_VALUE_SLOT, or(nodes, index)), 0)
169+
}
161170
}
162171
return 0;
163172
}

test/RedBlackTreeWithResize.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {LibSort} from "../src/lib/LibSort.sol";
77
import {LibPRNG} from "../src/lib/LibPRNG.sol";
88
import {RedBlackTreeWithResizeLib} from "../src/lib/RedBlackTreeWithResizeLib.sol";
99

10-
contract RedBlackTreeLibTest is SoladyTest {
10+
contract RedBlackTreeWithResizeLibTest is SoladyTest {
1111
using RedBlackTreeWithResizeLib for *;
1212
using LibPRNG for *;
1313

0 commit comments

Comments
 (0)