Skip to content

Commit

Permalink
Cleaning up Mnemonic.Strength and Wordlist
Browse files Browse the repository at this point in the history
  • Loading branch information
Sajjon committed Sep 18, 2019
1 parent d58c070 commit 6c82e3f
Show file tree
Hide file tree
Showing 13 changed files with 54 additions and 77 deletions.
2 changes: 1 addition & 1 deletion Sources/BitcoinKit/Core/Mnemonic/Mnemonic+Generate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 }

Expand Down
100 changes: 34 additions & 66 deletions Sources/BitcoinKit/Core/Mnemonic/Mnemonic+Strength.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import Foundation

// swiftlint:disable file_length
public extension WordList {
public extension Mnemonic.WordList {
static var english: [String] = {
let words =
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import Foundation

// swiftlint:disable file_length
public extension WordList {
public extension Mnemonic.WordList {
static var french: [String] = {
let words =
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import Foundation

// swiftlint:disable file_length
public extension WordList {
public extension Mnemonic.WordList {
static var italian: [String] = {
let words =
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import Foundation

// swiftlint:disable file_length
public extension WordList {
public extension Mnemonic.WordList {
static var japanese: [String] = {
let words =
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import Foundation

// swiftlint:disable file_length
public extension WordList {
public extension Mnemonic.WordList {
static var korean: [String] = {
let words =
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import Foundation

// swiftlint:disable file_length
public extension WordList {
public extension Mnemonic.WordList {
static var simplifiedChinese: [String] = {
let words =
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import Foundation

// swiftlint:disable file_length
public extension WordList {
public extension Mnemonic.WordList {
static var spanish: [String] = {
let words =
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import Foundation

// swiftlint:disable file_length
public extension WordList {
public extension Mnemonic.WordList {
static var traditionalChinese: [String] = {
let words =
"""
Expand Down
9 changes: 8 additions & 1 deletion Sources/BitcoinKit/Core/Mnemonic/WordList/WordList.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
2 changes: 2 additions & 0 deletions Sources/BitcoinKit/Extensions/Data_Extensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@

import Foundation

internal let bitsPerByte = 8

extension Data {
var binaryString: String {
var result: [String] = []
Expand Down
2 changes: 1 addition & 1 deletion Tests/BitcoinKitTests/MnemonicTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 }()

Expand Down

0 comments on commit 6c82e3f

Please sign in to comment.