@@ -8,39 +8,39 @@ import Foundation
8
8
9
9
struct Base58 {
10
10
static let base58Alphabet = " 123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz "
11
-
11
+
12
12
// Encode
13
13
static func base58FromBytes( _ bytes: [ UInt8 ] ) -> String {
14
14
var bytes = bytes
15
15
var zerosCount = 0
16
16
var length = 0
17
-
17
+
18
18
for b in bytes {
19
19
if b != 0 { break }
20
20
zerosCount += 1
21
21
}
22
-
22
+
23
23
bytes. removeFirst ( zerosCount)
24
-
24
+
25
25
let size = bytes. count * 138 / 100 + 1
26
-
26
+
27
27
var base58 : [ UInt8 ] = Array ( repeating: 0 , count: size)
28
28
for b in bytes {
29
29
var carry = Int ( b)
30
30
var i = 0
31
-
31
+
32
32
for j in 0 ... base58. count- 1 where carry != 0 || i < length {
33
33
carry += 256 * Int( base58 [ base58. count - j - 1 ] )
34
34
base58 [ base58. count - j - 1 ] = UInt8 ( carry % 58 )
35
35
carry /= 58
36
36
i += 1
37
37
}
38
-
38
+
39
39
assert ( carry == 0 )
40
-
40
+
41
41
length = i
42
42
}
43
-
43
+
44
44
// skip leading zeros
45
45
var zerosToRemove = 0
46
46
var str = " "
@@ -49,41 +49,44 @@ struct Base58 {
49
49
zerosToRemove += 1
50
50
}
51
51
base58. removeFirst ( zerosToRemove)
52
-
52
+
53
53
while 0 < zerosCount {
54
54
str = " \( str) 1 "
55
55
zerosCount -= 1
56
56
}
57
-
57
+
58
58
for b in base58 {
59
- //str = "\(str)\(base58Alphabet[String.Index(encodedOffset: Int(b))])"
60
59
str = " \( str) \( base58Alphabet [ String . Index ( utf16Offset: Int ( b) , in: base58Alphabet) ] ) "
61
60
}
62
-
61
+
63
62
return str
64
63
}
65
-
64
+
66
65
// Decode
67
66
static func bytesFromBase58( _ base58: String ) -> [ UInt8 ] {
68
67
// remove leading and trailing whitespaces
69
68
let string = base58. trimmingCharacters ( in: CharacterSet . whitespaces)
70
-
71
69
guard !string. isEmpty else { return [ ] }
72
-
73
- var zerosCount = 0
74
- var length = 0
70
+
71
+ // count leading "1"'s [decodes directly to zero bytes]
72
+ var leadingZeros = 0
75
73
for c in string {
76
74
if c != " 1 " { break }
77
- zerosCount += 1
75
+ leadingZeros += 1
78
76
}
79
-
80
- let size = string. lengthOfBytes ( using: String . Encoding. utf8) * 733 / 1000 + 1 - zerosCount
81
- var base58 : [ UInt8 ] = Array ( repeating: 0 , count: size)
77
+
78
+ // calculate the size of the decoded output, rounded up
79
+ let size = ( string. lengthOfBytes ( using: String . Encoding. utf8) - leadingZeros) * 733 / 1000 + 1
80
+
81
+ // allocate a buffer large enough for the decoded output
82
+ var base58 : [ UInt8 ] = Array ( repeating: 0 , count: size + leadingZeros)
83
+
84
+ // decode what remains of the data
85
+ var length = 0
82
86
for c in string where c != " " {
83
87
// search for base58 character
84
- guard let base58Index = base58Alphabet. index ( of: c) else { return [ ] }
85
-
86
- // var carry = base58Index.encodedOffset
88
+ guard let base58Index = base58Alphabet. firstIndex ( of: c) else { return [ ] }
89
+
87
90
var carry = base58Index. utf16Offset ( in: base58Alphabet)
88
91
var i = 0
89
92
for j in 0 ... base58. count where carry != 0 || i < length {
@@ -92,42 +95,36 @@ struct Base58 {
92
95
carry /= 256
93
96
i += 1
94
97
}
95
-
98
+
96
99
assert ( carry == 0 )
97
100
length = i
98
101
}
99
-
100
- // skip leading zeros
101
- var zerosToRemove = 0
102
-
102
+
103
+ // calculate how many leading zero bytes we have
104
+ var totalZeros = 0
103
105
for b in base58 {
104
106
if b != 0 { break }
105
- zerosToRemove += 1
107
+ totalZeros += 1
106
108
}
107
- base58. removeFirst ( zerosToRemove)
108
-
109
- var result : [ UInt8 ] = Array ( repeating: 0 , count: zerosCount)
110
- for b in base58 {
111
- result. append ( b)
112
- }
113
- return result
109
+ // remove the excess zero bytes
110
+ base58. removeFirst ( totalZeros - leadingZeros)
111
+
112
+ return base58
114
113
}
115
114
}
116
115
117
-
118
-
119
116
extension Array where Element == UInt8 {
120
117
public var base58EncodedString : String {
121
118
guard !self . isEmpty else { return " " }
122
119
return Base58 . base58FromBytes ( self )
123
120
}
124
-
121
+
125
122
public var base58CheckEncodedString : String {
126
123
var bytes = self
127
124
let checksum = [ UInt8] ( bytes. sha256 ( ) . sha256 ( ) [ 0 ..< 4 ] )
128
-
125
+
129
126
bytes. append ( contentsOf: checksum)
130
-
127
+
131
128
return Base58 . base58FromBytes ( bytes)
132
129
}
133
130
}
@@ -136,35 +133,28 @@ extension String {
136
133
public var base58EncodedString : String {
137
134
return [ UInt8] ( utf8) . base58EncodedString
138
135
}
139
-
136
+
140
137
public var base58DecodedData : Data ? {
141
138
let bytes = Base58 . bytesFromBase58 ( self )
142
139
return Data ( bytes)
143
140
}
144
-
141
+
145
142
public var base58CheckDecodedData : Data ? {
146
143
guard let bytes = self . base58CheckDecodedBytes else { return nil }
147
144
return Data ( bytes)
148
145
}
149
-
146
+
150
147
public var base58CheckDecodedBytes : [ UInt8 ] ? {
151
148
var bytes = Base58 . bytesFromBase58 ( self )
152
149
guard 4 <= bytes. count else { return nil }
153
-
150
+
154
151
let checksum = [ UInt8] ( bytes [ bytes. count- 4 ..< bytes. count] )
155
152
bytes = [ UInt8] ( bytes [ 0 ..< bytes. count- 4 ] )
156
-
153
+
157
154
let calculatedChecksum = [ UInt8] ( bytes. sha256 ( ) . sha256 ( ) [ 0 ... 3 ] )
158
155
if checksum != calculatedChecksum { return nil }
159
-
156
+
160
157
return bytes
161
158
}
162
-
163
- // public var littleEndianHexToUInt: UInt {
164
- // let data = Data.fromHex(self)!
165
- // let revensed =
166
- // return UInt(sel)
167
- // return UInt(self.dataWithHexString().bytes.reversed().fullHexString,radix: 16)!
168
- // }
169
-
159
+
170
160
}
0 commit comments