@@ -14,7 +14,11 @@ library Base58 {
14
14
using SafeCast for bool ;
15
15
using Bytes for bytes ;
16
16
17
- string internal constant _TABLE = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz " ;
17
+ error InvalidBase56Digit (uint8 );
18
+
19
+ bytes internal constant _TABLE = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz " ;
20
+ bytes internal constant _LOOKUP_TABLE =
21
+ hex "000102030405060708ffffffffffffff090a0b0c0d0e0f10ff1112131415ff161718191a1b1c1d1e1f20ffffffffffff2122232425262728292a2bff2c2d2e2f30313233343536373839 " ;
18
22
19
23
function encode (bytes memory data ) internal pure returns (string memory ) {
20
24
return string (_encode (data));
@@ -45,7 +49,7 @@ library Base58 {
45
49
length -= slotCLZ - dataCLZ;
46
50
slot.splice (slotCLZ - dataCLZ);
47
51
48
- bytes memory cache = bytes ( _TABLE) ;
52
+ bytes memory cache = _TABLE;
49
53
for (uint256 i = 0 ; i < length; ++ i) {
50
54
// equivalent to `slot[i] = TABLE[slot[i]];`
51
55
_mstore8 (slot, i, _mload8 (cache, _mload8i (slot, i)));
@@ -62,22 +66,29 @@ library Base58 {
62
66
uint256 size = 2 * ((b58Length * 8351 ) / 6115 + 1 );
63
67
bytes memory binu = new bytes (size);
64
68
65
- bytes memory cache = bytes (_TABLE);
66
- uint32 [] memory outi = new uint32 []((b58Length + 3 ) / 4 );
67
- for (uint256 i = 0 ; i < data.length ; i++ ) {
68
- bytes1 r = _mload8 (data, i);
69
- uint256 c = cache.indexOf (r); // can we avoid the loop here ?
70
- require (c != type (uint256 ).max, "invalid base58 digit " );
71
- for (uint256 k = outi.length ; k > 0 ; -- k) {
72
- uint256 t = uint64 (outi[k - 1 ]) * 58 + c;
73
- c = t >> 32 ;
74
- outi[k - 1 ] = uint32 (t & 0xffffffff );
69
+ bytes memory cache = _LOOKUP_TABLE;
70
+ uint256 outiLength = (b58Length + 3 ) / 4 ;
71
+ // Note: allocating uint32[] would be enough, but solidity doesn't pack memory.
72
+ uint256 [] memory outi = new uint256 [](outiLength);
73
+ for (uint256 i = 0 ; i < data.length ; ++ i) {
74
+ // get b58 char
75
+ uint8 chr = _mload8i (data, i);
76
+ require (chr > 48 && chr < 123 , InvalidBase56Digit (chr));
77
+
78
+ // decode b58 char
79
+ uint256 carry = _mload8i (cache, chr - 49 );
80
+ require (carry < 58 , InvalidBase56Digit (chr));
81
+
82
+ for (uint256 j = outiLength; j > 0 ; -- j) {
83
+ uint256 value = carry + 58 * outi[j - 1 ];
84
+ carry = value >> 32 ;
85
+ outi[j - 1 ] = value & 0xffffffff ;
75
86
}
76
87
}
77
88
78
89
uint256 ptr = 0 ;
79
90
uint256 mask = ((b58Length - 1 ) % 4 ) + 1 ;
80
- for (uint256 j = 0 ; j < outi. length ; ++ j) {
91
+ for (uint256 j = 0 ; j < outiLength ; ++ j) {
81
92
while (mask > 0 ) {
82
93
-- mask;
83
94
_mstore8 (binu, ptr, bytes1 (uint8 (outi[j] >> (8 * mask))));
0 commit comments