From 6c82e3fd1c6a9a23e1443b6c7cb6882fcb1deb21 Mon Sep 17 00:00:00 2001 From: Sajjon Date: Wed, 18 Sep 2019 13:24:23 +0200 Subject: [PATCH] Cleaning up Mnemonic.Strength and Wordlist --- .../Core/Mnemonic/Mnemonic+Generate.swift | 2 +- .../Core/Mnemonic/Mnemonic+Strength.swift | 100 ++++++------------ .../Mnemonic/WordList/WordList+English.swift | 2 +- .../Mnemonic/WordList/WordList+French.swift | 2 +- .../Mnemonic/WordList/WordList+Italian.swift | 2 +- .../Mnemonic/WordList/WordList+Japanese.swift | 2 +- .../Mnemonic/WordList/WordList+Korean.swift | 2 +- .../WordList/WordList+SimplifiedChinese.swift | 2 +- .../Mnemonic/WordList/WordList+Spanish.swift | 2 +- .../WordList+TraditionalChinese.swift | 2 +- .../Core/Mnemonic/WordList/WordList.swift | 9 +- .../Extensions/Data_Extensions.swift | 2 + Tests/BitcoinKitTests/MnemonicTests.swift | 2 +- 13 files changed, 54 insertions(+), 77 deletions(-) diff --git a/Sources/BitcoinKit/Core/Mnemonic/Mnemonic+Generate.swift b/Sources/BitcoinKit/Core/Mnemonic/Mnemonic+Generate.swift index dd6f0508..dc595d10 100644 --- a/Sources/BitcoinKit/Core/Mnemonic/Mnemonic+Generate.swift +++ b/Sources/BitcoinKit/Core/Mnemonic/Mnemonic+Generate.swift @@ -41,7 +41,7 @@ internal extension Mnemonic { let bits = BitArray(data: entropy) + checkSumBit - let wordIndices = bits.splitIntoChunks(ofSize: wordListSizeLog2) + let wordIndices = bits.splitIntoChunks(ofSize: Mnemonic.WordList.sizeLog2) .map { UInt11(bitArray: $0)! } .map { $0.asInt } diff --git a/Sources/BitcoinKit/Core/Mnemonic/Mnemonic+Strength.swift b/Sources/BitcoinKit/Core/Mnemonic/Mnemonic+Strength.swift index 604700b7..6926b05d 100644 --- a/Sources/BitcoinKit/Core/Mnemonic/Mnemonic+Strength.swift +++ b/Sources/BitcoinKit/Core/Mnemonic/Mnemonic+Strength.swift @@ -8,86 +8,54 @@ import Foundation -internal let bitsPerByte = 8 -internal let wordListSizeLog2 = 11 // 2^11 => 2048 - // MARK: Strength public extension Mnemonic { - enum Strength: Int, CaseIterable { - case `default` = 128 - case low = 160 - case medium = 192 - case high = 224 - case veryHigh = 256 - } + enum Strength: Int, CaseIterable { + case `default` = 128 + case low = 160 + case medium = 192 + case high = 224 + case veryHigh = 256 + } } public extension Mnemonic.Strength { - init?(wordCount: Int) { - guard - let entropyInBitsFromWordCount = Mnemonic.Strength.entropyInBitsFrom(wordCount: wordCount), - let strength = Self(rawValue: entropyInBitsFromWordCount) - else { return nil } - self = strength - } - init?(byteCount: Int) { - let bitCount = byteCount * bitsPerByte - guard - let strength = Self(rawValue: bitCount) - else { return nil } - self = strength - } + /// `wordCount` must be divisible by `3`, else `nil` is returned + init?(wordCount: Int) { + guard wordCount % Mnemonic.Strength.checksumBitsPerWord == 0 else { return nil } + let entropyInBitsFromWordCount = (wordCount / Mnemonic.Strength.checksumBitsPerWord) * 32 + self.init(rawValue: entropyInBitsFromWordCount) + } + + init?(byteCount: Int) { + let bitCount = byteCount * bitsPerByte + guard + let strength = Self(rawValue: bitCount) + else { return nil } + self = strength + } } // MARK: - Internal internal extension Mnemonic.Strength { - var wordCount: WordCount { - let wordCountInt = Mnemonic.Strength.wordCountFrom(entropyInBits: rawValue) - guard let wordCount = WordCount(rawValue: wordCountInt) else { - fatalError("Missed to include word count: \(wordCountInt)") - } - return wordCount - } - - var byteCount: Int { - return rawValue / bitsPerByte - } - - static func wordCountFrom(entropyInBits: Int) -> Int { - return Int(ceil(Double(entropyInBits) / Double(wordListSizeLog2))) - } - /// `wordCount` must be divisible by `3`, else `nil` is returned - static func entropyInBitsFrom(wordCount: Int) -> Int? { - guard wordCount % Mnemonic.Strength.checksumBitsPerWord == 0 else { return nil } - return (wordCount / Mnemonic.Strength.checksumBitsPerWord) * 32 - } + static let checksumBitsPerWord = 3 - static let checksumBitsPerWord = 3 - var checksumLengthInBits: Int { - return wordCount.wordCount / Mnemonic.Strength.checksumBitsPerWord - } + var byteCount: Int { + return rawValue / bitsPerByte + } - var checksumLengthInBytes: Int { - return checksumLengthInBits / bitsPerByte - } -} + var wordCount: Int { + return Mnemonic.Strength.wordCountFrom(entropyInBits: rawValue) + } -// MARK: - WordCount -internal extension Mnemonic.Strength { - enum WordCount: Int { - case wordCountOf12 = 12 - case wordCountOf15 = 15 - case wordCountOf18 = 18 - case wordCountOf21 = 21 - case wordCountOf24 = 24 - } -} + static func wordCountFrom(entropyInBits: Int) -> Int { + return Int(ceil(Double(entropyInBits) / Double(Mnemonic.WordList.sizeLog2))) + } -internal extension Mnemonic.Strength.WordCount { - var wordCount: Int { - return rawValue - } + var checksumLengthInBits: Int { + return wordCount / Mnemonic.Strength.checksumBitsPerWord + } } diff --git a/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+English.swift b/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+English.swift index 597b9c57..bb3e4694 100644 --- a/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+English.swift +++ b/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+English.swift @@ -26,7 +26,7 @@ import Foundation // swiftlint:disable file_length -public extension WordList { +public extension Mnemonic.WordList { static var english: [String] = { let words = """ diff --git a/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+French.swift b/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+French.swift index 5e3bc8f6..b9a9c7d0 100644 --- a/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+French.swift +++ b/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+French.swift @@ -26,7 +26,7 @@ import Foundation // swiftlint:disable file_length -public extension WordList { +public extension Mnemonic.WordList { static var french: [String] = { let words = """ diff --git a/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+Italian.swift b/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+Italian.swift index ecf87337..c2cc2f85 100644 --- a/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+Italian.swift +++ b/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+Italian.swift @@ -26,7 +26,7 @@ import Foundation // swiftlint:disable file_length -public extension WordList { +public extension Mnemonic.WordList { static var italian: [String] = { let words = """ diff --git a/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+Japanese.swift b/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+Japanese.swift index 67048888..833f72a8 100644 --- a/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+Japanese.swift +++ b/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+Japanese.swift @@ -26,7 +26,7 @@ import Foundation // swiftlint:disable file_length -public extension WordList { +public extension Mnemonic.WordList { static var japanese: [String] = { let words = """ diff --git a/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+Korean.swift b/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+Korean.swift index 5c771a69..40ce93d6 100644 --- a/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+Korean.swift +++ b/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+Korean.swift @@ -26,7 +26,7 @@ import Foundation // swiftlint:disable file_length -public extension WordList { +public extension Mnemonic.WordList { static var korean: [String] = { let words = """ diff --git a/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+SimplifiedChinese.swift b/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+SimplifiedChinese.swift index dbdbe129..98d61a05 100644 --- a/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+SimplifiedChinese.swift +++ b/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+SimplifiedChinese.swift @@ -26,7 +26,7 @@ import Foundation // swiftlint:disable file_length -public extension WordList { +public extension Mnemonic.WordList { static var simplifiedChinese: [String] = { let words = """ diff --git a/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+Spanish.swift b/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+Spanish.swift index 3ba12f2e..652c7ff6 100644 --- a/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+Spanish.swift +++ b/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+Spanish.swift @@ -26,7 +26,7 @@ import Foundation // swiftlint:disable file_length -public extension WordList { +public extension Mnemonic.WordList { static var spanish: [String] = { let words = """ diff --git a/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+TraditionalChinese.swift b/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+TraditionalChinese.swift index 0d0e41c4..96fef784 100644 --- a/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+TraditionalChinese.swift +++ b/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList+TraditionalChinese.swift @@ -26,7 +26,7 @@ import Foundation // swiftlint:disable file_length -public extension WordList { +public extension Mnemonic.WordList { static var traditionalChinese: [String] = { let words = """ diff --git a/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList.swift b/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList.swift index ab9b1e71..cee6593f 100644 --- a/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList.swift +++ b/Sources/BitcoinKit/Core/Mnemonic/WordList/WordList.swift @@ -25,4 +25,11 @@ import Foundation -public enum WordList {} +public extension Mnemonic { + enum WordList {} +} + +internal extension Mnemonic.WordList { + /// `2^11 => 2048` + static let sizeLog2 = 11 +} diff --git a/Sources/BitcoinKit/Extensions/Data_Extensions.swift b/Sources/BitcoinKit/Extensions/Data_Extensions.swift index 25270185..a2d951dd 100644 --- a/Sources/BitcoinKit/Extensions/Data_Extensions.swift +++ b/Sources/BitcoinKit/Extensions/Data_Extensions.swift @@ -24,6 +24,8 @@ import Foundation +internal let bitsPerByte = 8 + extension Data { var binaryString: String { var result: [String] = [] diff --git a/Tests/BitcoinKitTests/MnemonicTests.swift b/Tests/BitcoinKitTests/MnemonicTests.swift index 4eab3b99..33c619d7 100644 --- a/Tests/BitcoinKitTests/MnemonicTests.swift +++ b/Tests/BitcoinKitTests/MnemonicTests.swift @@ -468,7 +468,7 @@ private extension MnemonicTests { } XCTAssertNoThrow(try Mnemonic.validateChecksumOf(mnemonic: words, language: .english), "validation of vector with mnemonic failed: '\(words)'") - let firstWordInVocabulary = WordList.english.first! + let firstWordInVocabulary = Mnemonic.WordList.english.first! XCTAssertNotEqual(words[0], firstWordInVocabulary) // assert that we dont have such bad luck that the first let mnemonicFirstWordReplaced: [String] = { var tmp = words; tmp[0] = firstWordInVocabulary; return tmp }()