@@ -40,8 +40,8 @@ library Base58 {
40
40
function _encode (bytes memory data ) private pure returns (bytes memory encoded ) {
41
41
// For reference, solidity implementation
42
42
// unchecked {
43
- // uint256 dataCLZ = data.countLeading(0x00);
44
- // uint256 length = dataCLZ + ((data.length - dataCLZ ) * 8351) / 6115 + 1;
43
+ // uint256 dataLeadingZeros = data.countLeading(0x00);
44
+ // uint256 length = dataLeadingZeros + ((data.length - dataLeadingZeros ) * 8351) / 6115 + 1;
45
45
// encoded = new bytes(length);
46
46
// uint256 end = length;
47
47
// for (uint256 i = 0; i < data.length; ++i) {
@@ -54,8 +54,8 @@ library Base58 {
54
54
// end = ptr;
55
55
// }
56
56
// uint256 encodedCLZ = encoded.countLeading(0x00);
57
- // length -= encodedCLZ - dataCLZ ;
58
- // encoded.splice(encodedCLZ - dataCLZ );
57
+ // length -= encodedCLZ - dataLeadingZeros ;
58
+ // encoded.splice(encodedCLZ - dataLeadingZeros );
59
59
// for (uint256 i = 0; i < length; ++i) {
60
60
// encoded[i] = _TABLE[uint8(encoded[i])];
61
61
// }
@@ -86,11 +86,12 @@ library Base58 {
86
86
encoded := mload (0x40 )
87
87
let dataLength := mload (data)
88
88
89
- // Count number of zero bytes at the beginning of `data`
90
- let dataCLZ := clzBytes (add (data, 0x20 ), dataLength)
89
+ // Count number of zero bytes at the beginning of `data`. These are encoded using the same number of '1's
90
+ // at then beginning of the encoded string.
91
+ let dataLeadingZeros := clzBytes (add (data, 0x20 ), dataLength)
91
92
92
- // Initial encoding
93
- let slotLength := add (add (dataCLZ, div (mul (sub (dataLength, dataCLZ ), 8351 ), 6115 ) ), 1 )
93
+ // Initial encoding length: 100% of zero bytes (zero prefix) + 138% of non zero bytes + 1
94
+ let slotLength := add (add (div (mul (sub (dataLength, dataLeadingZeros ), 138 ), 100 ), dataLeadingZeros ), 1 )
94
95
95
96
// Zero the encoded buffer
96
97
for {
@@ -121,17 +122,19 @@ library Base58 {
121
122
end := ptr
122
123
}
123
124
124
- // Count number of zero bytes at the beginning of slots
125
- let slotCLZ := clzBytes (add (encoded, 0x20 ), slotLength)
125
+ // Count number of zero bytes at the beginning of slots. This is a pointer to the first non zero slot that
126
+ // contains the base58 data. This base58 data span over `slotLength-slotLeadingZeros` bytes.
127
+ let slotLeadingZeros := clzBytes (add (encoded, 0x20 ), slotLength)
126
128
127
- // Update length
128
- let offset := sub (slotCLZ, dataCLZ )
129
+ // Update length: `slotLength-slotLeadingZeros` of non-zero data plus `dataLeadingZeros` of zero prefix.
130
+ let offset := sub (slotLeadingZeros, dataLeadingZeros )
129
131
let encodedLength := sub (slotLength, offset)
130
132
131
133
// Store the encoding table. This overlaps with the FMP that we are going to reset later anyway.
132
134
mstore (0x1f , "123456789ABCDEFGHJKLMNPQRSTUVWXY " )
133
135
mstore (0x3f , "Zabcdefghijkmnopqrstuvwxyz " )
134
136
137
+ // For each slot, use the table to obtain the corresponding base58 "digit".
135
138
for {
136
139
let i := 0
137
140
} lt (i, encodedLength) {
@@ -140,7 +143,7 @@ library Base58 {
140
143
mstore8 (add (add (encoded, 0x20 ), i), mload (shr (248 , mload (add (add (encoded, 0x20 ), add (offset, i))))))
141
144
}
142
145
143
- // Store length and allocate memory
146
+ // Store length and allocate (reserve) memory
144
147
mstore (encoded, encodedLength)
145
148
mstore (0x40 , add (add (encoded, 0x20 ), encodedLength))
146
149
}
@@ -184,9 +187,9 @@ library Base58 {
184
187
mask = 4 ;
185
188
}
186
189
187
- uint256 dataCLZ = data.countLeading (0x31 );
188
- uint256 msb = binu.countConsecutive (dataCLZ , 0x00 );
189
- return binu.splice (msb * (dataCLZ + msb < binu.length ).toUint (), ptr);
190
+ uint256 dataLeadingZeros = data.countLeading (0x31 );
191
+ uint256 msb = binu.countConsecutive (dataLeadingZeros , 0x00 );
192
+ return binu.splice (msb * (dataLeadingZeros + msb < binu.length ).toUint (), ptr);
190
193
}
191
194
}
192
195
0 commit comments