Skip to content
This repository has been archived by the owner on May 28, 2019. It is now read-only.

Conform Bitcoin to BIP49 #53

Merged
merged 6 commits into from
Sep 12, 2018
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Sources/Bitcoin/Bitcoin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ open class Bitcoin: Blockchain {
return .bitcoin
}

override open var coinPurpose: Purpose {
return .bip49
}

/// Public key hash address prefix.
open var publicKeyHashAddressPrefix: UInt8 {
return 0x00
Expand Down
6 changes: 4 additions & 2 deletions Sources/Bitcoin/PublicKey+Bitcoin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import Foundation
public extension PublicKey {
/// Returns the public key address with the given prefix.
public func bitcoinAddress(prefix: UInt8) -> BitcoinAddress {
let hash = Data([prefix]) + Crypto.sha256ripemd160(data)
return BitcoinAddress(data: hash)!
let witnessVersion = Data([0x00] + [0x14])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Data(bytes: [0x00, 0x14])

let redeemScript = Crypto.sha256ripemd160(witnessVersion + bitcoinKeyHash)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is specific to p2sh-p2wpkh is should be on a separate function: bitcoinSegWitAddress?

let address = Crypto.base58Encode([prefix] + redeemScript)
return BitcoinAddress(string: address)!
}

/// Returns the public key hash.
Expand Down
6 changes: 5 additions & 1 deletion Sources/Blockchain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ open class Blockchain: Hashable {
fatalError("Use a specific Blockchain subclass")
}

open var coinPurpose: Purpose {
return .bip44
}

public init() {}

/// Returns the address associated with a public key.
Expand Down Expand Up @@ -45,6 +49,6 @@ open class Blockchain: Hashable {

public extension Blockchain {
func derivationPath(at index: Int) -> DerivationPath {
return DerivationPath(purpose: 44, coinType: self.coinType.rawValue, account: 0, change: 0, address: index)
return DerivationPath(purpose: coinPurpose.rawValue, coinType: coinType.rawValue, account: 0, change: 0, address: index)
}
}
4 changes: 4 additions & 0 deletions Sources/Ethereum/Ethereum.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ open class Ethereum: Blockchain {
return .ethereum
}

open override var coinPurpose: Purpose {
return .bip44
}

open override func address(for publicKey: PublicKey) -> Address {
return publicKey.ethereumAddress
}
Expand Down
14 changes: 14 additions & 0 deletions Sources/Purpose.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Copyright © 2017-2018 Trust.
//
// This file is part of Trust. The full Trust copyright notice, including
// terms governing use, modification, and redistribution, is contained in the
// file LICENSE at the root of the source code distribution tree.

import Foundation

// See https://github.com/bitcoin/bips/blob/master/bip-0049.mediawiki

public enum Purpose: Int {
case bip44 = 44
case bip49 = 49
}
5 changes: 2 additions & 3 deletions Tests/Bitcoin/BitcoinAddressTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,11 @@ class BitcoinAddressTests: XCTestCase {
}

func testFromPrivateKey() {
let data = Crypto.base58Decode("5K6EwEiKWKNnWGYwbNtrXjA8KKNntvxNKvepNqNeeLpfW7FSG1v")!
let privateKey = PrivateKey(data: data.dropFirst())!
let privateKey = PrivateKey(wif: "L5XECLxq1MDvBeYXjZwz5tTYsFZRWmaYziY3Wvc2bqSRAuRcBqhg")!
let publicKey = privateKey.publicKey(compressed: true)
let address = Bitcoin().address(for: publicKey)

XCTAssertEqual(address.description, "3EpNJiTASbZ6DeNA7QZ7bPEz82Y42W8Rd7")
XCTAssertEqual(address.description, "3Hv6oV8BYCoocW4eqZaEXsaR5tHhCxiMSk")
}

func testIsValid() {
Expand Down
9 changes: 9 additions & 0 deletions Tests/HDWalletTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,15 @@ class HDWalletTests: XCTestCase {
XCTAssertEqual(key1.publicKey().ethereumAddress.description, "0x98f5438cDE3F0Ff6E11aE47236e93481899d1C47")
}

func testDeriveBitcoin() {
let wallet = HDWallet(mnemonic: words, passphrase: passphrase)
let key = wallet.getKey(at: Bitcoin().derivationPath(at: 0))
let publicKey = key.publicKey(compressed: true)

XCTAssertEqual("026fc80db3a34e7c6bfc6d7d9a53aeba9e706b309c9cf7ee96fa9c36ff7fd92a20", publicKey.description)
XCTAssertEqual("3FJjnZNXC6FWQ2UJAaKL3Vme2EJavfgnXe", publicKey.bitcoinAddress(prefix: Bitcoin().payToScriptHashAddressPrefix).description)
}

func testSignHash() {
let wallet = HDWallet(mnemonic: words, passphrase: passphrase)
let key = wallet.getKey(at: Ethereum().derivationPath(at: 0))
Expand Down
21 changes: 21 additions & 0 deletions Tests/PurposeTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright © 2017-2018 Trust.
//
// This file is part of Trust. The full Trust copyright notice, including
// terms governing use, modification, and redistribution, is contained in the
// file LICENSE at the root of the source code distribution tree.

import XCTest
import TrustCore

class PurposeTests: XCTestCase {

func testPurpose() {
XCTAssertEqual(.bip49, Bitcoin().coinPurpose)
XCTAssertEqual(.bip49, Litecoin().coinPurpose)
XCTAssertEqual(.bip49, Dash().coinPurpose)
XCTAssertEqual(.bip44, Ethereum().coinPurpose)
XCTAssertEqual(.bip44, Wanchain().coinPurpose)
XCTAssertEqual(.bip44, Vechain().coinPurpose)
XCTAssertEqual(.bip44, Go().coinPurpose)
}
}
8 changes: 8 additions & 0 deletions TrustCore.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@
77F80A892134A5220011D949 /* VechainTransactionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77F80A882134A5220011D949 /* VechainTransactionTests.swift */; };
77F80A9421363D5C0011D949 /* CryptoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77F80A9321363D5C0011D949 /* CryptoTests.swift */; };
77F8D3B02141CBB900E80CD6 /* DashTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77F8D3AF2141CBB900E80CD6 /* DashTests.swift */; };
77F8D3DB214860D200E80CD6 /* Purpose.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77F8D3DA214860D200E80CD6 /* Purpose.swift */; };
77F8D3DF2148625100E80CD6 /* PurposeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 77F8D3DE2148625100E80CD6 /* PurposeTests.swift */; };
887FD54919AD2FA39E88EAF0 /* Pods_TrustCore_TrustCoreTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1C9DA59AE410E04E68E1F89 /* Pods_TrustCore_TrustCoreTests.framework */; };
BB06149A920620338B3323D1 /* Pods_TrustCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 682B6374F9856982618A8501 /* Pods_TrustCore.framework */; };
BB1215D021390A4D0092FC68 /* ERC721EncoderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB1215CF21390A4D0092FC68 /* ERC721EncoderTests.swift */; };
Expand Down Expand Up @@ -172,6 +174,8 @@
77F80A882134A5220011D949 /* VechainTransactionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VechainTransactionTests.swift; sourceTree = "<group>"; };
77F80A9321363D5C0011D949 /* CryptoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CryptoTests.swift; sourceTree = "<group>"; };
77F8D3AF2141CBB900E80CD6 /* DashTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DashTests.swift; sourceTree = "<group>"; };
77F8D3DA214860D200E80CD6 /* Purpose.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Purpose.swift; sourceTree = "<group>"; };
77F8D3DE2148625100E80CD6 /* PurposeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PurposeTests.swift; sourceTree = "<group>"; };
99258028638D3902B177E80C /* Pods-TrustCore.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TrustCore.debug.xcconfig"; path = "Pods/Target Support Files/Pods-TrustCore/Pods-TrustCore.debug.xcconfig"; sourceTree = "<group>"; };
A1C9DA59AE410E04E68E1F89 /* Pods_TrustCore_TrustCoreTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_TrustCore_TrustCoreTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
BB1215CF21390A4D0092FC68 /* ERC721EncoderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ERC721EncoderTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -252,6 +256,7 @@
615AE1D720F1D66000A5A0ED /* PublicKey.swift */,
61A728D220F46ECF0005045D /* String+Clear.swift */,
7749DFEE2141105800411ED8 /* Slip.swift */,
77F8D3DA214860D200E80CD6 /* Purpose.swift */,
615AE1D120F1D1BA00A5A0ED /* Bitcoin */,
615AE1D420F1D56C00A5A0ED /* Ethereum */,
61A728E620F487F50005045D /* HDWallet */,
Expand Down Expand Up @@ -286,6 +291,7 @@
77F80A872134A50A0011D949 /* VeChain */,
7749DFEC21410F1B00411ED8 /* SlipTests.swift */,
77F8D3AF2141CBB900E80CD6 /* DashTests.swift */,
77F8D3DE2148625100E80CD6 /* PurposeTests.swift */,
);
path = Tests;
sourceTree = "<group>";
Expand Down Expand Up @@ -689,6 +695,7 @@
61D0BA292075D771004F71E1 /* ABIEncoder.swift in Sources */,
612B85D4212BC35100F5BCF5 /* BitcoinTransaction+Signing.swift in Sources */,
BB3864C3209569CE00CBF773 /* ReverseResolverEncoder.swift in Sources */,
77F8D3DB214860D200E80CD6 /* Purpose.swift in Sources */,
6167556C207ABBEF00018DC8 /* ABIType.swift in Sources */,
77044FAF212F9F8E00CC20D1 /* WanchainSigner.swift in Sources */,
61675588207C745700018DC8 /* ERC20Encoder.swift in Sources */,
Expand Down Expand Up @@ -716,6 +723,7 @@
buildActionMask = 2147483647;
files = (
77044FBE2131378F00CC20D1 /* TronTests.swift in Sources */,
77F8D3DF2148625100E80CD6 /* PurposeTests.swift in Sources */,
BB3864C720956F8B00CBF773 /* ReverseResolverEncoderTests.swift in Sources */,
61555865208ED04F00FB241E /* TransactionSigningTests.swift in Sources */,
6149A6D0201E4B6B00A2F35C /* EthereumAddressTests.swift in Sources */,
Expand Down