montana/Монтана-iOS/Tests/MontanaAppTests/MnemonicTests.swift

87 lines
3.7 KiB
Swift
Raw Permalink Normal View History

import XCTest
@testable import MontanaApp
final class MnemonicTests: XCTestCase {
/// spec, раздел "Test vectors (binding) M-1 Vector 1"
/// entropy = [0x00; 32]
/// mnemonic = "abandon abandon ... abandon art"
/// master_seed = 38a1421ac3ce191fbdc46b1cca266a9d72d22320fb38bda6a3df90a1ead664a7
/// 8951703197be882ace38e0f557a492a8e9ff5e3c02290a8eecf5939468708edb
func testM1Vector1_ZeroEntropy() throws {
let entropy = Data(count: 32)
let mnemonic = try Mnemonic.encode(entropy: entropy)
XCTAssertEqual(mnemonic.split(whereSeparator: { $0.isWhitespace }).count, 24)
XCTAssertTrue(mnemonic.hasSuffix(" art"), "BIP-39 standard: zero entropy + checksum 0x66 → word 'art'")
let masterSeed = try Mnemonic.decodeAndDerive(mnemonic: mnemonic)
let hex = masterSeed.map { String(format: "%02x", $0) }.joined()
XCTAssertEqual(hex,
"38a1421ac3ce191fbdc46b1cca266a9d72d22320fb38bda6a3df90a1ead664a7" +
"8951703197be882ace38e0f557a492a8e9ff5e3c02290a8eecf5939468708edb"
)
}
/// spec, раздел "Test vectors (binding) M-1 Vector 2"
/// entropy = [0xFF; 32]
/// master_seed = a5925c51583447a0abe43b65dbc591f3780a91c7d44c6b333975a211096039f3
/// d1d0ca9e125aa4e756f0a35b0006378ac69450e8254e32f16409a350f3ca9104
func testM1Vector2_MaxEntropy() throws {
let entropy = Data(repeating: 0xFF, count: 32)
let mnemonic = try Mnemonic.encode(entropy: entropy)
XCTAssertTrue(mnemonic.hasSuffix(" vote"))
let masterSeed = try Mnemonic.decodeAndDerive(mnemonic: mnemonic)
let hex = masterSeed.map { String(format: "%02x", $0) }.joined()
XCTAssertEqual(hex,
"a5925c51583447a0abe43b65dbc591f3780a91c7d44c6b333975a211096039f3" +
"d1d0ca9e125aa4e756f0a35b0006378ac69450e8254e32f16409a350f3ca9104"
)
}
func testWordlistFingerprint() {
XCTAssertTrue(Wordlist.verifyBindingFingerprint(),
"wordlist.txt SHA-256 должен соответствовать spec binding fingerprint")
}
func testGenerateProduces24Words() {
let m = Mnemonic.generate()
XCTAssertEqual(m.split(whereSeparator: { $0.isWhitespace }).count, 24)
}
func testRoundtrip() throws {
let entropy = Data((0..<32).map { _ in UInt8.random(in: 0...255) })
let mnemonic = try Mnemonic.encode(entropy: entropy)
let seed1 = try Mnemonic.decodeAndDerive(mnemonic: mnemonic)
let seed2 = try Mnemonic.decodeAndDerive(mnemonic: mnemonic)
XCTAssertEqual(seed1, seed2, "Determinism")
}
func testInvalidWordCount() {
XCTAssertThrowsError(try Mnemonic.decodeAndDerive(mnemonic: "abandon abandon")) { err in
if case Mnemonic.MnemonicError.wordCount(let n) = err {
XCTAssertEqual(n, 2)
} else {
XCTFail("expected wordCount error")
}
}
}
func testInvalidWord() {
let bad = Array(repeating: "abandon", count: 23).joined(separator: " ") + " bogusword"
XCTAssertThrowsError(try Mnemonic.decodeAndDerive(mnemonic: bad)) { err in
if case Mnemonic.MnemonicError.unknownWord(let pos) = err {
XCTAssertEqual(pos, 23)
} else {
XCTFail("expected unknownWord error")
}
}
}
func testInvalidChecksum() {
let m = Array(repeating: "abandon", count: 24).joined(separator: " ")
XCTAssertThrowsError(try Mnemonic.decodeAndDerive(mnemonic: m)) { err in
XCTAssertEqual(err as? Mnemonic.MnemonicError, .checksumMismatch)
}
}
}