From 44a9cdfc33e9384c521d98854bfcd726b8282e27 Mon Sep 17 00:00:00 2001 From: pebble8888 Date: Tue, 4 Sep 2018 22:26:28 +0900 Subject: [PATCH 1/7] Add merkleblock and proof of work check --- BitcoinKit.xcodeproj/project.pbxproj | 46 ++++ Sources/BitcoinKit/Core/Math.swift | 19 ++ Sources/BitcoinKit/Core/MerkleTree.swift | 80 ++++++ Sources/BitcoinKit/Core/ProofOfWork.swift | 38 +++ Sources/BitcoinKit/Core/UInt256+Bitcoin.swift | 34 +++ Sources/BitcoinKit/Core/UInt256.swift | 234 ++++++++++++++++++ Sources/BitcoinKit/Core/UInt32+Utility.swift | 13 + Sources/BitcoinKit/Networking/PeerGroup.swift | 18 ++ Tests/BitcoinKitTests/ProofOfWorkTests.swift | 25 ++ .../BitcoinKitTests/SerializationTests.swift | 34 +++ .../UInt256+BitcoinTests.swift | 100 ++++++++ Tests/BitcoinKitTests/UInt256Tests.swift | 199 +++++++++++++++ Tests/BitcoinKitTests/UInt32MathTests.swift | 43 ++++ 13 files changed, 883 insertions(+) create mode 100644 Sources/BitcoinKit/Core/Math.swift create mode 100644 Sources/BitcoinKit/Core/MerkleTree.swift create mode 100644 Sources/BitcoinKit/Core/ProofOfWork.swift create mode 100644 Sources/BitcoinKit/Core/UInt256+Bitcoin.swift create mode 100644 Sources/BitcoinKit/Core/UInt256.swift create mode 100644 Sources/BitcoinKit/Core/UInt32+Utility.swift create mode 100644 Tests/BitcoinKitTests/ProofOfWorkTests.swift create mode 100644 Tests/BitcoinKitTests/SerializationTests.swift create mode 100644 Tests/BitcoinKitTests/UInt256+BitcoinTests.swift create mode 100644 Tests/BitcoinKitTests/UInt256Tests.swift create mode 100644 Tests/BitcoinKitTests/UInt32MathTests.swift diff --git a/BitcoinKit.xcodeproj/project.pbxproj b/BitcoinKit.xcodeproj/project.pbxproj index 1336d9cf..19a51b80 100644 --- a/BitcoinKit.xcodeproj/project.pbxproj +++ b/BitcoinKit.xcodeproj/project.pbxproj @@ -206,6 +206,17 @@ 6E20AED72112D417008A9810 /* MurmurHashTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E20AED62112D417008A9810 /* MurmurHashTests.swift */; }; 6E797C452116C8A5003BEDFD /* OpCodeFactoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6E797C442116C8A5003BEDFD /* OpCodeFactoryTests.swift */; }; 6EE789DB2112C1E500EAB620 /* CryptoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6EE789DA2112C1E500EAB620 /* CryptoTests.swift */; }; + A20B537F211C72F9009D147A /* UInt256Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A20B537E211C72F9009D147A /* UInt256Tests.swift */; }; + A246ED102118621B0000418D /* MerkleTree.swift in Sources */ = {isa = PBXBuildFile; fileRef = A246ED0F2118621B0000418D /* MerkleTree.swift */; }; + A246ED12211864500000418D /* UInt256.swift in Sources */ = {isa = PBXBuildFile; fileRef = A246ED11211864500000418D /* UInt256.swift */; }; + A2613884211E8E12003A3B29 /* UInt256+Bitcoin.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2613883211E8E12003A3B29 /* UInt256+Bitcoin.swift */; }; + A29721F8211B2497007228D5 /* Math.swift in Sources */ = {isa = PBXBuildFile; fileRef = A29721F7211B2497007228D5 /* Math.swift */; }; + A2B7A34E2125464400764AE9 /* ProofOfWork.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2B7A34D2125464400764AE9 /* ProofOfWork.swift */; }; + A2DAA5F7211F0579009DAB7B /* UInt32MathTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2DAA5F6211F0579009DAB7B /* UInt32MathTests.swift */; }; + A2DAA5F9211F2C93009DAB7B /* SerializationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2DAA5F8211F2C93009DAB7B /* SerializationTests.swift */; }; + A2DE5110212AFCF200F54EA0 /* UInt256+BitcoinTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2DE510F212AFCF200F54EA0 /* UInt256+BitcoinTests.swift */; }; + A2E11231212C400A00A0A40A /* ProofOfWorkTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2E11230212C400A00A0A40A /* ProofOfWorkTests.swift */; }; + A2F06FBA2126785200DFF652 /* UInt32+Utility.swift in Sources */ = {isa = PBXBuildFile; fileRef = A2F06FB92126785200DFF652 /* UInt32+Utility.swift */; }; CF432AF220F0CF9100AD4020 /* Base58Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF432AF120F0CF9100AD4020 /* Base58Tests.swift */; }; CF432AF420F0DFAC00AD4020 /* Bech32Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF432AF320F0DFAC00AD4020 /* Bech32Tests.swift */; }; CF432AF620F0ED4500AD4020 /* AddressTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF432AF520F0ED4500AD4020 /* AddressTests.swift */; }; @@ -433,6 +444,17 @@ 6E20AED62112D417008A9810 /* MurmurHashTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MurmurHashTests.swift; sourceTree = ""; }; 6E797C442116C8A5003BEDFD /* OpCodeFactoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpCodeFactoryTests.swift; sourceTree = ""; }; 6EE789DA2112C1E500EAB620 /* CryptoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CryptoTests.swift; sourceTree = ""; }; + A20B537E211C72F9009D147A /* UInt256Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UInt256Tests.swift; sourceTree = ""; }; + A246ED0F2118621B0000418D /* MerkleTree.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MerkleTree.swift; sourceTree = ""; }; + A246ED11211864500000418D /* UInt256.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UInt256.swift; sourceTree = ""; }; + A2613883211E8E12003A3B29 /* UInt256+Bitcoin.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UInt256+Bitcoin.swift"; sourceTree = ""; }; + A29721F7211B2497007228D5 /* Math.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Math.swift; sourceTree = ""; }; + A2B7A34D2125464400764AE9 /* ProofOfWork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProofOfWork.swift; sourceTree = ""; }; + A2DAA5F6211F0579009DAB7B /* UInt32MathTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UInt32MathTests.swift; sourceTree = ""; }; + A2DAA5F8211F2C93009DAB7B /* SerializationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SerializationTests.swift; sourceTree = ""; }; + A2DE510F212AFCF200F54EA0 /* UInt256+BitcoinTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UInt256+BitcoinTests.swift"; sourceTree = ""; }; + A2E11230212C400A00A0A40A /* ProofOfWorkTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProofOfWorkTests.swift; sourceTree = ""; }; + A2F06FB92126785200DFF652 /* UInt32+Utility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UInt32+Utility.swift"; sourceTree = ""; }; CF432AF120F0CF9100AD4020 /* Base58Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Base58Tests.swift; sourceTree = ""; }; CF432AF320F0DFAC00AD4020 /* Bech32Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Bech32Tests.swift; sourceTree = ""; }; CF432AF520F0ED4500AD4020 /* AddressTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressTests.swift; sourceTree = ""; }; @@ -577,6 +599,11 @@ 6E20AED62112D417008A9810 /* MurmurHashTests.swift */, 6E797C442116C8A5003BEDFD /* OpCodeFactoryTests.swift */, 29089F0D2122BE7200E0C305 /* MockHelperTests.swift */, + A20B537E211C72F9009D147A /* UInt256Tests.swift */, + A2DAA5F6211F0579009DAB7B /* UInt32MathTests.swift */, + A2DAA5F8211F2C93009DAB7B /* SerializationTests.swift */, + A2DE510F212AFCF200F54EA0 /* UInt256+BitcoinTests.swift */, + A2E11230212C400A00A0A40A /* ProofOfWorkTests.swift */, ); name = BitcoinKitTests; path = Tests/BitcoinKitTests; @@ -622,12 +649,19 @@ 1482B5E32026F2580098B612 /* WordList.swift */, 14839A7B202F79F900A6CB34 /* PaymentURI.swift */, 147494E3201F9B85006D1CF8 /* Crypto.swift */, + 147494E5201F9BEF006D1CF8 /* Encoding.swift */, + A29721F7211B2497007228D5 /* Math.swift */, + A246ED0F2118621B0000418D /* MerkleTree.swift */, + A2B7A34D2125464400764AE9 /* ProofOfWork.swift */, 147494EF201FAE30006D1CF8 /* Serialization.swift */, 14F37A3D2020A02000D34748 /* SighashType.swift */, 29330F6D210597B700106AFA /* UnitsAndLimits.swift */, 299CB47220F0185500B1245C /* TransactionSignatureSerializer.swift */, 299CB46E20EE1EA500B1245C /* Transaction+SignatureHash.swift */, 2949920120F228B400D078B6 /* UnspentTransaction.swift */, + A2F06FB92126785200DFF652 /* UInt32+Utility.swift */, + A246ED11211864500000418D /* UInt256.swift */, + A2613883211E8E12003A3B29 /* UInt256+Bitcoin.swift */, 2949920520F22DCA00D078B6 /* UnsignedTransaction.swift */, 14839AA4202FE7A100A6CB34 /* ByteStream.swift */, 147F9728201FC89E0071F49D /* BloomFilter.swift */, @@ -1085,6 +1119,7 @@ 29E1ED75210EF071007F4627 /* OP_CHECKMULTISIGVERIFY.swift in Sources */, 294DDE3F211B31CB00B7F645 /* OP_IF.swift in Sources */, 29290B8D210AF59600D2BE78 /* OpCodeFactory.swift in Sources */, + A246ED102118621B0000418D /* MerkleTree.swift in Sources */, 147F9729201FC89E0071F49D /* BloomFilter.swift in Sources */, 0C1DD40A211819CE004BA8A8 /* OP_GREATERTHAN.swift in Sources */, 2914BE49211BAB1900B349CB /* OP_CODESEPARATOR.swift in Sources */, @@ -1093,12 +1128,15 @@ 2914BE52211BCF9600B349CB /* OP_RESERVED2.swift in Sources */, 0C66CD05212542660049DB89 /* OP_AND.swift in Sources */, 0C1DD41021181AF3004BA8A8 /* OP_NUMEQUAL.swift in Sources */, + A2613884211E8E12003A3B29 /* UInt256+Bitcoin.swift in Sources */, 14839AA9202FE7DD00A6CB34 /* VarString.swift in Sources */, 14F37A3E2020A02000D34748 /* SighashType.swift in Sources */, + A2F06FBA2126785200DFF652 /* UInt32+Utility.swift in Sources */, 14839A8F202FE68000A6CB34 /* PongMessage.swift in Sources */, 294DDE41211B31D600B7F645 /* OP_NOTIF.swift in Sources */, 0C1DE161211E717500FE8E43 /* OP_OVER.swift in Sources */, 0C1DD42321182126004BA8A8 /* OP_MOD.swift in Sources */, + A29721F8211B2497007228D5 /* Math.swift in Sources */, 29290B9B210AF88C00D2BE78 /* OP_HASH160.swift in Sources */, 14CDC3862021824200C01556 /* Wallet.swift in Sources */, 0C1DE165211E75A800FE8E43 /* OP_ROLL.swift in Sources */, @@ -1137,7 +1175,9 @@ 147494E4201F9B85006D1CF8 /* Crypto.swift in Sources */, 2933014F214FCE2D0028946B /* TransactionBroadcaster.swift in Sources */, 0C0900422116B9DE0077E9BC /* OP_LSHIFT.swift in Sources */, + A2B7A34E2125464400764AE9 /* ProofOfWork.swift in Sources */, 14839A9F202FE73B00A6CB34 /* TransactionOutput.swift in Sources */, + A246ED12211864500000418D /* UInt256.swift in Sources */, 1463E6B62025E99C0033DAAE /* BlockChain.swift in Sources */, 2914BE4E211BCF7600B349CB /* OP_RESERVED.swift in Sources */, 14839A81202FE5CA00A6CB34 /* VerackMessage.swift in Sources */, @@ -1214,6 +1254,8 @@ buildActionMask = 2147483647; files = ( 147494D6201F9A29006D1CF8 /* BitcoinKitTests.swift in Sources */, + A2DE5110212AFCF200F54EA0 /* UInt256+BitcoinTests.swift in Sources */, + 147494D6201F9A29006D1CF8 /* BitcoinCashKitTests.swift in Sources */, CFA290742102B650001A1BAB /* ScriptMachineTests.swift in Sources */, 6E20AECB2112C434008A9810 /* HDPrivateKeyTests.swift in Sources */, 6E20AED52112C8F9008A9810 /* BloomFilterTests.swift in Sources */, @@ -1227,17 +1269,21 @@ 6E797C452116C8A5003BEDFD /* OpCodeFactoryTests.swift in Sources */, CF432AFC20F25E0000AD4020 /* TestHelpersTests.swift in Sources */, 0C2375A52132507B00DB2872 /* MessageSerializerTests.swift in Sources */, + A2E11231212C400A00A0A40A /* ProofOfWorkTests.swift in Sources */, CFA290702101CDCA001A1BAB /* ScriptTests.swift in Sources */, 6E20AECF2112C66C008A9810 /* HDKeyChainTests.swift in Sources */, CF432AF420F0DFAC00AD4020 /* Bech32Tests.swift in Sources */, 29089F0E2122BE7200E0C305 /* MockHelperTests.swift in Sources */, 6E20AECD2112C559008A9810 /* CashAddrTests.swift in Sources */, + A2DAA5F7211F0579009DAB7B /* UInt32MathTests.swift in Sources */, 29F5D1E02110495F007DA3BF /* OpCodeTests.swift in Sources */, 6E20AEC92112C31A008A9810 /* LegacyAddressTests.swift in Sources */, 6E20AED12112C6AA008A9810 /* PaymentURITests.swift in Sources */, CF432AF220F0CF9100AD4020 /* Base58Tests.swift in Sources */, + A2DAA5F9211F2C93009DAB7B /* SerializationTests.swift in Sources */, 2949920420F22A1500D078B6 /* TestHelpers.swift in Sources */, 29F5D1E421106772007DA3BF /* BigNumberTests.swift in Sources */, + A20B537F211C72F9009D147A /* UInt256Tests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Sources/BitcoinKit/Core/Math.swift b/Sources/BitcoinKit/Core/Math.swift new file mode 100644 index 00000000..2e666c89 --- /dev/null +++ b/Sources/BitcoinKit/Core/Math.swift @@ -0,0 +1,19 @@ +// +// UInt32+Math.swift +// +// Copyright © 2018 pebble8888 All rights reserved. +// + +import Foundation + +func ceil_log2(_ x: UInt32) -> UInt32 { + if x == 0 { return 0 } + var xx = x + var r: UInt32 = (xx & (xx-1)) != 0 ? 1 : 0 + while true { + xx >>= 1 + if xx == 0 { break } + r += 1 + } + return r +} diff --git a/Sources/BitcoinKit/Core/MerkleTree.swift b/Sources/BitcoinKit/Core/MerkleTree.swift new file mode 100644 index 00000000..b3e48fba --- /dev/null +++ b/Sources/BitcoinKit/Core/MerkleTree.swift @@ -0,0 +1,80 @@ +// +// MerkleTree.swift +// +// Copyright © 2018 pebble8888 All rights reserved. +// + +import Foundation + +struct MerkleTree { + enum MerkleError: Error { + case noEnoughParent + case noEnoughHash + case duplicateHash // CVE-2012-2459 + case invalidNumberOfHashes + case invalidNumberOfFlags + case nullHash + } + + static func buildMerkleRoot(numberOfHashes: UInt32, hashes: [Data], numberOfFlags: UInt32, flags: [UInt8], + totalTransactions: UInt32) throws -> Data + { + if numberOfHashes != hashes.count { + throw MerkleError.invalidNumberOfHashes + } + if flags.count < numberOfFlags/8 { + throw MerkleError.invalidNumberOfFlags + } + let parents: [Bool] = (0 ..< Int(numberOfFlags)).compactMap({ + return (flags[$0/8] & UInt8(1 << ($0 % 8))) != 0 + }) + let maxdepth: UInt = UInt(ceil_log2(totalTransactions)) + var hashIterator = hashes.makeIterator() + var parentIterator = parents.makeIterator() + let root = try buildPartialMerkleTree(hashIterator: &hashIterator, parentIterator: &parentIterator, depth: 0, maxdepth: maxdepth) + guard let h = root.hash else { throw MerkleError.nullHash } + return h + } + + struct PartialMerkleTree { + var hash: Data? + // zero size if depth is maxdepth + // leaf[0]: left, leaf[1]: right + var leaf: [PartialMerkleTree] = [] + init(hash: Data, leafL: PartialMerkleTree, leafR: PartialMerkleTree){ + self.hash = hash + leaf.append(leafL) + leaf.append(leafR) + } + init(hash: Data){ + self.hash = hash + } + } + + private static func buildPartialMerkleTree( + hashIterator: inout IndexingIterator>, + parentIterator: inout IndexingIterator>, + depth: UInt, maxdepth: UInt) throws -> PartialMerkleTree + { + guard let parent = parentIterator.next() else { throw MerkleError.noEnoughParent } + if !parent || maxdepth <= depth { + // leaf + guard let hash = hashIterator.next() else { throw MerkleError.noEnoughHash } + return PartialMerkleTree(hash: hash) + } else { + // vertex + let left: PartialMerkleTree = try buildPartialMerkleTree(hashIterator: &hashIterator, parentIterator: &parentIterator, depth: depth + 1, maxdepth: maxdepth) + let right: PartialMerkleTree = try buildPartialMerkleTree(hashIterator: &hashIterator, parentIterator: &parentIterator, depth: depth + 1, maxdepth: maxdepth) + if let h0 = left.hash, let h1 = right.hash { + if h0 == h1 { + // CVE-2012-2459 + throw MerkleError.duplicateHash + } + let hash = Crypto.sha256sha256(h0 + h1) + return PartialMerkleTree(hash: hash, leafL: left, leafR: right) + } else { + throw MerkleError.nullHash + } + } + } +} diff --git a/Sources/BitcoinKit/Core/ProofOfWork.swift b/Sources/BitcoinKit/Core/ProofOfWork.swift new file mode 100644 index 00000000..bb038042 --- /dev/null +++ b/Sources/BitcoinKit/Core/ProofOfWork.swift @@ -0,0 +1,38 @@ +// +// ProofOfWork.swift +// +// Copyright © 2018 pebble8888 All rights reserved. +// + +import Foundation + +class ProofOfWork { + static let maxProofOfWork: UInt256 + = UInt256(data: Data(hex:"00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff")!)! + static func isValidProofOfWork(blockHash: Data, bits: UInt32) -> Bool { + let target: UInt256 + do { + target = try UInt256(compact: bits) + } catch { + // invalid bits + return false + } + if target == UInt256.zero { + // invalid zero target + return false + } + if target > maxProofOfWork { + // too high target + return false + } + guard let arith_hash = UInt256(data: blockHash) else { + // invalid blockHash data length + return false + } + if arith_hash > target { + // insufficient proof of work + return false + } + return true + } +} diff --git a/Sources/BitcoinKit/Core/UInt256+Bitcoin.swift b/Sources/BitcoinKit/Core/UInt256+Bitcoin.swift new file mode 100644 index 00000000..b82e3be2 --- /dev/null +++ b/Sources/BitcoinKit/Core/UInt256+Bitcoin.swift @@ -0,0 +1,34 @@ +// +// UInt256+bitcoin.swift +// +// Copyright © 2018 pebble8888 All rights reserved. +// + +import Foundation + +extension UInt256 { + public enum CompactError: Error { + case negative, overflow + } + // bitcoin "compact" format + public init(compact: UInt32) throws { + let size: UInt32 = compact >> 24 + let target: UInt32 = compact & 0x007fffff + if target == 0 { + self = UInt256.zero + } else { + // The 0x00800000 denotes the sign + if (compact & 0x00800000) != 0 { + throw CompactError.negative + } + if size > 0x22 || (target > 0xff && size > 0x21) || (target > 0xffff && size > 0x20) { + throw CompactError.overflow + } + if size < 3 { + self = UInt256(target) >> ((3 - size) * 8) + } else { + self = UInt256(target) << ((size - 3) * 8) + } + } + } +} diff --git a/Sources/BitcoinKit/Core/UInt256.swift b/Sources/BitcoinKit/Core/UInt256.swift new file mode 100644 index 00000000..d6b2586d --- /dev/null +++ b/Sources/BitcoinKit/Core/UInt256.swift @@ -0,0 +1,234 @@ +// +// UInt256.swift +// +// Copyright © 2018 pebble8888 All rights reserved. +// + +import Foundation + +// UInt256 corresponds to `arith_uint256` in the original bitcoin core. +struct UInt256 { + enum UInt256Error: Error { + case invalidDataSize + } + public static var max: UInt256 { + return UInt256(UInt64.max, UInt64.max, UInt64.max, UInt64.max) + } + public static var bitWidth: Int { get { return 256 } } + public static let byteWidth = UInt256.bitWidth / 8 + static let elementCount = byteWidth / 8 + + // e0 is lowest digit (UInt64 value is LittleEndian) + // e3 is highest digit (UInt64 value is LittleEndian) + private var e0: UInt64 + private var e1: UInt64 + private var e2: UInt64 + private var e3: UInt64 + + public static let zero = UInt256() + + init() { + e0 = 0 + e1 = 0 + e2 = 0 + e3 = 0 + } + + init(_ e0: UInt64, _ e1: UInt64, _ e2: UInt64, _ e3: UInt64) + { + self.e0 = e0 + self.e1 = e1 + self.e2 = e2 + self.e3 = e3 + } + + // 64bytes "01 00 00 00 ... 00" + // : UInt256(1) + init?(data: Data) { + if data.count != UInt256.byteWidth { return nil } + // little endian cast + e0 = data[0..<8].to(type: UInt64.self) + e1 = data[8..<16].to(type: UInt64.self) + e2 = data[16..<24].to(type: UInt64.self) + e3 = data[24..<32].to(type: UInt64.self) + } + + // hex: MSB representation + // "_" is ignored in parsing + // UInt256(hex: "00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000001") + // : UInt256(1) + init?(hex: String) { + let h = hex.replacingOccurrences(of: "_", with: "") + // big endian + guard let data = Data(hex: h)?.reversed() else { return nil } + self.init(data: Data(data)) + } + + public init(_ val: UInt) { + // set to lowest digit + self = UInt256(UInt64(val), 0, 0, 0) + } + + public init(_ val: UInt64){ + self = UInt256(val, 0, 0, 0) + } + + public init(_ val: UInt32){ + self = UInt256(UInt64(val)) + } + + public init(_ val: UInt16){ + self = UInt256(UInt64(val)) + } + + public init(_ val: UInt8){ + self = UInt256(UInt64(val)) + } +} + +extension UInt256: CustomDebugStringConvertible { + public var debugDescription: String { + return self.hex + } +} + +extension UInt256 : Equatable { + public static func == (lhs: UInt256, rhs: UInt256) -> Bool { + if lhs.e0 != rhs.e0 { return false } + else if lhs.e1 != rhs.e1 { return false } + else if lhs.e2 != rhs.e2 { return false } + else if lhs.e3 != rhs.e3 { return false } + return true + } +} + +extension UInt256 : Comparable { + public static func < (lhs: UInt256, rhs: UInt256) -> Bool { + // compare higest digit at first + if lhs.e3 != rhs.e3 { return lhs.e3 < rhs.e3 } + else if lhs.e2 != rhs.e2 { return lhs.e2 < rhs.e2 } + else if lhs.e1 != rhs.e1 { return lhs.e1 < rhs.e1 } + else if lhs.e0 != rhs.e0 { return lhs.e0 < rhs.e0 } + // a < a is always false (Irreflexivity) + return false + } +} + +extension UInt64 { + // MSB representation + public var hex: String { + return String(format:"%016lx", self) + } +} + +extension UInt256 { + // MSB representation + public var hex: String { + return [e3, e2, e1, e0].map({ $0.hex }).joined(separator: "") + } +} + +extension UInt256 { + public var data: Data { + // little endian cast + return Data(from: e0) + Data(from: e1) + Data(from: e2) + Data(from: e3) + } +} + +protocol BitShiftOperator { + static func >> (lhs: Self, rhs: RHS) -> Self where RHS : UnsignedInteger + static func << (lhs: Self, rhs: RHS) -> Self where RHS : UnsignedInteger +} + +extension UInt256: BitShiftOperator { + public static func >> (lhs: UInt256, rhs: RHS) -> UInt256 where RHS : UnsignedInteger + { + if rhs < 64 { + var v = UInt256() + let mask = bitValue(bit: UInt(rhs)) + let shift = 64 - rhs + v.e3 = lhs.e3 >> rhs + v.e2 = (lhs.e2 >> rhs) + ((lhs.e3 & mask) << shift) + v.e1 = (lhs.e1 >> rhs) + ((lhs.e2 & mask) << shift) + v.e0 = (lhs.e0 >> rhs) + ((lhs.e1 & mask) << shift) + return v + } else if rhs < 128 { + var v = UInt256() + let mask = bitValue(bit: UInt(rhs-64)) + let shift = 128 - rhs + v.e3 = 0 + v.e2 = (lhs.e3 >> (rhs-64)) + v.e1 = (lhs.e2 >> (rhs-64)) + ((lhs.e3 & mask) << shift) + v.e0 = (lhs.e1 >> (rhs-64)) + ((lhs.e2 & mask) << shift) + return v + } else if rhs < 192 { + var v = UInt256() + let mask = bitValue(bit: UInt(rhs-128)) + let shift = 192 - rhs + v.e3 = 0 + v.e2 = 0 + v.e1 = (lhs.e3 >> (rhs-128)) + v.e0 = (lhs.e2 >> (rhs-128)) + ((lhs.e3 & mask) << shift) + return v + } else if rhs < 256 { + var v = UInt256() + v.e3 = 0 + v.e2 = 0 + v.e1 = 0 + v.e0 = (lhs.e3 >> (rhs-192)) + return v + } else { + return UInt256.zero + } + } + + public static func << (lhs: UInt256, rhs: RHS) -> UInt256 where RHS : UnsignedInteger + { + if rhs < 64 { + var v = UInt256() + let rev = rhs + let shift = 64 - rhs + v.e3 = (lhs.e3 << rev) + (lhs.e2 >> shift) + v.e2 = (lhs.e2 << rev) + (lhs.e1 >> shift) + v.e1 = (lhs.e1 << rev) + (lhs.e0 >> shift) + v.e0 = (lhs.e0 << rev) + return v + } else if rhs < 128 { + var v = UInt256() + let rev = rhs - 64 + let shift = 128 - rhs + v.e3 = (lhs.e2 << rev) + (lhs.e1 >> shift) + v.e2 = (lhs.e1 << rev) + (lhs.e0 >> shift) + v.e1 = (lhs.e0 << rev) + v.e0 = 0 + return v + } else if rhs < 192 { + var v = UInt256() + let rev = rhs - 128 + let shift = 192 - rhs + v.e3 = (lhs.e1 << rev) + (lhs.e0 >> shift) + v.e2 = (lhs.e0 << rev) + v.e1 = 0 + v.e0 = 0 + return v + } else if rhs < 256 { + var v = UInt256() + let rev = rhs - 192 + v.e3 = (lhs.e0 << rev) + v.e2 = 0 + v.e1 = 0 + v.e0 = 0 + return v + } else { + return UInt256.zero + } + } +} + +fileprivate func bitValue(bit: UInt) -> UInt64 { + var v:UInt64 = 0 + for i in 0 ..< bit { + v += (1 << i) + } + return v +} diff --git a/Sources/BitcoinKit/Core/UInt32+Utility.swift b/Sources/BitcoinKit/Core/UInt32+Utility.swift new file mode 100644 index 00000000..2fd7ee33 --- /dev/null +++ b/Sources/BitcoinKit/Core/UInt32+Utility.swift @@ -0,0 +1,13 @@ +// +// UInt32+Utility.swift +// +// Copyright © 2018 pebble8888 All rights reserved. +// + +import Foundation + +extension UInt32 { + public var hex: String { + return String(format:"%08x", self) + } +} diff --git a/Sources/BitcoinKit/Networking/PeerGroup.swift b/Sources/BitcoinKit/Networking/PeerGroup.swift index b57e5c40..57577487 100644 --- a/Sources/BitcoinKit/Networking/PeerGroup.swift +++ b/Sources/BitcoinKit/Networking/PeerGroup.swift @@ -103,6 +103,24 @@ public class PeerGroup: PeerDelegate { } public func peer(_ peer: Peer, didReceiveMerkleBlockMessage message: MerkleBlockMessage, hash: Data) { + if !ProofOfWork.isValidProofOfWork(blockHash: hash, bits: message.bits) { + print("insufficient proof of work!") + return + } + do { + let root: Data = try MerkleTree.buildMerkleRoot(numberOfHashes: UInt32(message.numberOfHashes.underlyingValue), + hashes: message.hashes, + numberOfFlags: UInt32(message.numberOfFlags.underlyingValue), + flags: message.flags, + totalTransactions: message.totalTransactions) + if root != message.merkleRoot { + print("not match merkelroot!") + return + } + } catch { + print("merkleroot build failed!") + return + } try! blockChain.addMerkleBlock(message, hash: hash) } diff --git a/Tests/BitcoinKitTests/ProofOfWorkTests.swift b/Tests/BitcoinKitTests/ProofOfWorkTests.swift new file mode 100644 index 00000000..bb8b21a0 --- /dev/null +++ b/Tests/BitcoinKitTests/ProofOfWorkTests.swift @@ -0,0 +1,25 @@ +// +// ProofOfWorkTests.swift +// +// Copyright © 2018 pebble8888 All rights reserved. +// + +import XCTest +@testable import BitcoinKit + +class ProofOfWorkTests: XCTestCase { + + override func setUp() { + super.setUp() + } + + override func tearDown() { + super.tearDown() + } + + func testExample() { + // TODO: + } + + +} diff --git a/Tests/BitcoinKitTests/SerializationTests.swift b/Tests/BitcoinKitTests/SerializationTests.swift new file mode 100644 index 00000000..da08fc1b --- /dev/null +++ b/Tests/BitcoinKitTests/SerializationTests.swift @@ -0,0 +1,34 @@ +// +// SerializationTests.swift +// +// Copyright © 2018 pebble8888 All rights reserved. +// + +import XCTest +@testable import BitcoinKit + +class SerializationTests: XCTestCase { + + override func setUp() { + super.setUp() + } + + override func tearDown() { + super.tearDown() + } + + func test1() { + let d = Data(bytes: [1, 2, 3, 4]) + let i: UInt32 = d.to(type: UInt32.self) + XCTAssertEqual(i.hex, "04030201") + XCTAssertEqual(i, 0x04030201) + } + + func test2() { + let d = Data(bytes: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]) + let i: UInt256 = d.to(type: UInt256.self) + XCTAssertEqual(i.hex, "0200000000000000000000000000000000000000000000000000000000000001") + } + + +} diff --git a/Tests/BitcoinKitTests/UInt256+BitcoinTests.swift b/Tests/BitcoinKitTests/UInt256+BitcoinTests.swift new file mode 100644 index 00000000..b99ab116 --- /dev/null +++ b/Tests/BitcoinKitTests/UInt256+BitcoinTests.swift @@ -0,0 +1,100 @@ +// +// UInt256+BitcoinTests.swift +// +// Copyright © 2018 pebble8888 All rights reserved. +// + +import XCTest +@testable import BitcoinKit + +class UInt256_BitcoinTests: XCTestCase { + + override func setUp() { + super.setUp() + } + + override func tearDown() { + super.tearDown() + } + + func test1() { + XCTAssertEqual(try UInt256(compact: UInt32(0x007fffff)).hex, "0000000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual(try UInt256(compact: UInt32(0x017fffff)).hex, "000000000000000000000000000000000000000000000000000000000000007f") + XCTAssertEqual(try UInt256(compact: UInt32(0x027fffff)).hex, "0000000000000000000000000000000000000000000000000000000000007fff") + XCTAssertEqual(try UInt256(compact: UInt32(0x03123456)).hex, "0000000000000000000000000000000000000000000000000000000000123456") + XCTAssertEqual(try UInt256(compact: UInt32(0x037fffff)).hex, "00000000000000000000000000000000000000000000000000000000007fffff") + XCTAssertEqual(try UInt256(compact: UInt32(0x047fffff)).hex, "000000000000000000000000000000000000000000000000000000007fffff00") + XCTAssertEqual(try UInt256(compact: UInt32(0x057fffff)).hex, "0000000000000000000000000000000000000000000000000000007fffff0000") + XCTAssertEqual(try UInt256(compact: UInt32(0x067fffff)).hex, "00000000000000000000000000000000000000000000000000007fffff000000") + XCTAssertEqual(try UInt256(compact: UInt32(0x077fffff)).hex, "000000000000000000000000000000000000000000000000007fffff00000000") + XCTAssertEqual(try UInt256(compact: UInt32(0x087fffff)).hex, "0000000000000000000000000000000000000000000000007fffff0000000000") + XCTAssertEqual(try UInt256(compact: UInt32(0x097fffff)).hex, "00000000000000000000000000000000000000000000007fffff000000000000") + XCTAssertEqual(try UInt256(compact: UInt32(0x1d7fffff)).hex, "0000007fffff0000000000000000000000000000000000000000000000000000") + XCTAssertEqual(try UInt256(compact: UInt32(0x1e7fffff)).hex, "00007fffff000000000000000000000000000000000000000000000000000000") + XCTAssertEqual(try UInt256(compact: UInt32(0x1f7fffff)).hex, "007fffff00000000000000000000000000000000000000000000000000000000") + XCTAssertEqual(try UInt256(compact: UInt32(0x207fffff)).hex, "7fffff0000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual(try UInt256(compact: UInt32(0x2100ffff)).hex, "ffff000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual(try UInt256(compact: UInt32(0x220000ff)).hex, "ff00000000000000000000000000000000000000000000000000000000000000") + } + + func testOverflow() { + do { + _ = try UInt256(compact: UInt32(0x21010000)) + XCTFail() + } catch UInt256.CompactError.overflow { + } catch { + XCTFail() + } + + do { + _ = try UInt256(compact: UInt32(0x22000100)) + XCTFail() + } catch UInt256.CompactError.overflow { + } catch { + XCTFail() + } + + do { + _ = try UInt256(compact: UInt32(0x23000001)) + XCTFail() + } catch UInt256.CompactError.overflow { + } catch { + XCTFail() + } + + do { + _ = try UInt256(compact: UInt32(0xff000001)) + XCTFail() + } catch UInt256.CompactError.overflow { + } catch { + XCTFail() + } + } + + // negative + func testNegative() { + do { + _ = try UInt256(compact: UInt32(0x008fffff)) + XCTFail() + } catch UInt256.CompactError.negative { + } catch { + XCTFail() + } + + do { + _ = try UInt256(compact: UInt32(0x009fffff)) + XCTFail() + } catch UInt256.CompactError.negative { + } catch { + XCTFail() + } + + do { + _ = try UInt256(compact: UInt32(0x00ffffff)) + XCTFail() + } catch UInt256.CompactError.negative { + } catch { + XCTFail() + } + } +} diff --git a/Tests/BitcoinKitTests/UInt256Tests.swift b/Tests/BitcoinKitTests/UInt256Tests.swift new file mode 100644 index 00000000..957e57a6 --- /dev/null +++ b/Tests/BitcoinKitTests/UInt256Tests.swift @@ -0,0 +1,199 @@ +// +// UInt256Tests.swift +// +// Copyright © 2018 pebble8888 All rights reserved. +// + +import XCTest +@testable import BitcoinKit + +class UInt256Tests: XCTestCase { + + override func setUp() { + super.setUp() + } + + override func tearDown() { + super.tearDown() + } + + func test1() { + let v: UInt256 = UInt256(UInt(1592868)) << UInt(200) + XCTAssert(v != UInt256.zero) + } + + func testzero() { + let v: UInt256 = UInt256(UInt(0)) + XCTAssert(v == UInt256.zero) + } + + func testUInt64() { + XCTAssertEqual(UInt64(1).hex, "0000000000000001") + XCTAssertEqual(UInt64.max.hex, "ffffffffffffffff") + } + + func testUInt256() { + XCTAssertEqual(UInt256(UInt(1)).hex, "0000000000000000000000000000000000000000000000000000000000000001") + XCTAssertEqual(UInt256.max.hex, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + } + + func testUInt256ShiftLeft1() { + XCTAssertEqual((UInt256(UInt(1)) << UInt(0)).hex, "0000000000000000000000000000000000000000000000000000000000000001") + XCTAssertEqual((UInt256(UInt(1)) << UInt(1)).hex, "0000000000000000000000000000000000000000000000000000000000000002") + XCTAssertEqual((UInt256(UInt(1)) << UInt(2)).hex, "0000000000000000000000000000000000000000000000000000000000000004") + XCTAssertEqual((UInt256(UInt(1)) << UInt(3)).hex, "0000000000000000000000000000000000000000000000000000000000000008") + XCTAssertEqual((UInt256(UInt(1)) << UInt(4)).hex, "0000000000000000000000000000000000000000000000000000000000000010") + XCTAssertEqual((UInt256(UInt(1)) << UInt(5)).hex, "0000000000000000000000000000000000000000000000000000000000000020") + XCTAssertEqual((UInt256(UInt(1)) << UInt(6)).hex, "0000000000000000000000000000000000000000000000000000000000000040") + XCTAssertEqual((UInt256(UInt(1)) << UInt(7)).hex, "0000000000000000000000000000000000000000000000000000000000000080") + XCTAssertEqual((UInt256(UInt(1)) << UInt(8)).hex, "0000000000000000000000000000000000000000000000000000000000000100") + XCTAssertEqual((UInt256(UInt(1)) << UInt(9)).hex, "0000000000000000000000000000000000000000000000000000000000000200") + XCTAssertEqual((UInt256(UInt(1)) << UInt(10)).hex, "0000000000000000000000000000000000000000000000000000000000000400") + XCTAssertEqual((UInt256(UInt(1)) << UInt(11)).hex, "0000000000000000000000000000000000000000000000000000000000000800") + XCTAssertEqual((UInt256(UInt(1)) << UInt(12)).hex, "0000000000000000000000000000000000000000000000000000000000001000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(13)).hex, "0000000000000000000000000000000000000000000000000000000000002000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(14)).hex, "0000000000000000000000000000000000000000000000000000000000004000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(15)).hex, "0000000000000000000000000000000000000000000000000000000000008000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(16)).hex, "0000000000000000000000000000000000000000000000000000000000010000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(17)).hex, "0000000000000000000000000000000000000000000000000000000000020000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(18)).hex, "0000000000000000000000000000000000000000000000000000000000040000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(19)).hex, "0000000000000000000000000000000000000000000000000000000000080000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(20)).hex, "0000000000000000000000000000000000000000000000000000000000100000") + + XCTAssertEqual((UInt256(UInt(1)) << UInt(30)).hex, "0000000000000000000000000000000000000000000000000000000040000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(40)).hex, "0000000000000000000000000000000000000000000000000000010000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(50)).hex, "0000000000000000000000000000000000000000000000000004000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(60)).hex, "0000000000000000000000000000000000000000000000001000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(70)).hex, "0000000000000000000000000000000000000000000000400000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(80)).hex, "0000000000000000000000000000000000000000000100000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(90)).hex, "0000000000000000000000000000000000000000040000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(100)).hex, "0000000000000000000000000000000000000010000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(110)).hex, "0000000000000000000000000000000000004000000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(120)).hex, "0000000000000000000000000000000001000000000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(130)).hex, "0000000000000000000000000000000400000000000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(140)).hex, "0000000000000000000000000000100000000000000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(150)).hex, "0000000000000000000000000040000000000000000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(160)).hex, "0000000000000000000000010000000000000000000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(170)).hex, "0000000000000000000004000000000000000000000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(180)).hex, "0000000000000000001000000000000000000000000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(190)).hex, "0000000000000000400000000000000000000000000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(200)).hex, "0000000000000100000000000000000000000000000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(210)).hex, "0000000000040000000000000000000000000000000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(220)).hex, "0000000010000000000000000000000000000000000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(230)).hex, "0000004000000000000000000000000000000000000000000000000000000000") + + XCTAssertEqual((UInt256(UInt(1)) << UInt(240)).hex, "0001000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(241)).hex, "0002000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(242)).hex, "0004000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(243)).hex, "0008000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(244)).hex, "0010000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(245)).hex, "0020000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(246)).hex, "0040000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(247)).hex, "0080000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(248)).hex, "0100000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(249)).hex, "0200000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(250)).hex, "0400000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(251)).hex, "0800000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(252)).hex, "1000000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(253)).hex, "2000000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(254)).hex, "4000000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(255)).hex, "8000000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual((UInt256(UInt(1)) << UInt(256)).hex, "0000000000000000000000000000000000000000000000000000000000000000") + } + + func testUInt256ShiftRight1() { + XCTAssertEqual((UInt256.max >> UInt(0)).hex, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(1)).hex, "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(2)).hex, "3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(3)).hex, "1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(4)).hex, "0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(5)).hex, "07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(6)).hex, "03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(7)).hex, "01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(8)).hex, "00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(9)).hex, "007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(10)).hex, "003fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(11)).hex, "001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(12)).hex, "000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(13)).hex, "0007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(14)).hex, "0003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(15)).hex, "0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(16)).hex, "0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(17)).hex, "00007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(18)).hex, "00003fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(19)).hex, "00001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(20)).hex, "00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + + XCTAssertEqual((UInt256.max >> UInt(30)).hex, "00000003ffffffffffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(40)).hex, "0000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(50)).hex, "0000000000003fffffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(60)).hex, "000000000000000fffffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(70)).hex, "000000000000000003ffffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(80)).hex, "00000000000000000000ffffffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(90)).hex, "00000000000000000000003fffffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(100)).hex, "0000000000000000000000000fffffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(110)).hex, "0000000000000000000000000003ffffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(120)).hex, "000000000000000000000000000000ffffffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(130)).hex, "000000000000000000000000000000003fffffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(140)).hex, "00000000000000000000000000000000000fffffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(150)).hex, "00000000000000000000000000000000000003ffffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(160)).hex, "0000000000000000000000000000000000000000ffffffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(170)).hex, "0000000000000000000000000000000000000000003fffffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(180)).hex, "000000000000000000000000000000000000000000000fffffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(190)).hex, "000000000000000000000000000000000000000000000003ffffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(200)).hex, "00000000000000000000000000000000000000000000000000ffffffffffffff") + XCTAssertEqual((UInt256.max >> UInt(210)).hex, "00000000000000000000000000000000000000000000000000003fffffffffff") + XCTAssertEqual((UInt256.max >> UInt(220)).hex, "0000000000000000000000000000000000000000000000000000000fffffffff") + XCTAssertEqual((UInt256.max >> UInt(230)).hex, "0000000000000000000000000000000000000000000000000000000003ffffff") + + XCTAssertEqual((UInt256.max >> UInt(240)).hex, "000000000000000000000000000000000000000000000000000000000000ffff") + XCTAssertEqual((UInt256.max >> UInt(241)).hex, "0000000000000000000000000000000000000000000000000000000000007fff") + XCTAssertEqual((UInt256.max >> UInt(242)).hex, "0000000000000000000000000000000000000000000000000000000000003fff") + XCTAssertEqual((UInt256.max >> UInt(243)).hex, "0000000000000000000000000000000000000000000000000000000000001fff") + XCTAssertEqual((UInt256.max >> UInt(244)).hex, "0000000000000000000000000000000000000000000000000000000000000fff") + XCTAssertEqual((UInt256.max >> UInt(245)).hex, "00000000000000000000000000000000000000000000000000000000000007ff") + XCTAssertEqual((UInt256.max >> UInt(246)).hex, "00000000000000000000000000000000000000000000000000000000000003ff") + XCTAssertEqual((UInt256.max >> UInt(247)).hex, "00000000000000000000000000000000000000000000000000000000000001ff") + XCTAssertEqual((UInt256.max >> UInt(248)).hex, "00000000000000000000000000000000000000000000000000000000000000ff") + XCTAssertEqual((UInt256.max >> UInt(249)).hex, "000000000000000000000000000000000000000000000000000000000000007f") + XCTAssertEqual((UInt256.max >> UInt(250)).hex, "000000000000000000000000000000000000000000000000000000000000003f") + XCTAssertEqual((UInt256.max >> UInt(251)).hex, "000000000000000000000000000000000000000000000000000000000000001f") + XCTAssertEqual((UInt256.max >> UInt(252)).hex, "000000000000000000000000000000000000000000000000000000000000000f") + XCTAssertEqual((UInt256.max >> UInt(253)).hex, "0000000000000000000000000000000000000000000000000000000000000007") + XCTAssertEqual((UInt256.max >> UInt(254)).hex, "0000000000000000000000000000000000000000000000000000000000000003") + XCTAssertEqual((UInt256.max >> UInt(255)).hex, "0000000000000000000000000000000000000000000000000000000000000001") + XCTAssertEqual((UInt256.max >> UInt(256)).hex, "0000000000000000000000000000000000000000000000000000000000000000") + } + + func testUInt256Hex1() { + XCTAssertEqual(UInt256(hex: "0102030405060708f1f2f3f4f5f6f7f8e1e2e3e4e5e6e7e8d1d2d3d4d5d6d7d8")!.hex, "0102030405060708f1f2f3f4f5f6f7f8e1e2e3e4e5e6e7e8d1d2d3d4d5d6d7d8") + XCTAssertEqual(UInt256(hex: "0102030405060708f1f2f3f4f5f6f7f8e1e2e3e4e5e6e7e8d1d2d3d4d5d6d7d8")!.data.hex, "d8d7d6d5d4d3d2d1e8e7e6e5e4e3e2e1f8f7f6f5f4f3f2f10807060504030201") + } + + func testUInt256Compare1() { + XCTAssertTrue(UInt256(hex: "00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000")! + < UInt256(hex: "00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000001")!) + + XCTAssertTrue(UInt256(hex: "00000000_f0000000_f0000000_f0000000_f0000000_f0000000_f0000000_f0000000")! + < UInt256(hex: "00000001_00000000_00000000_00000000_00000000_00000000_00000000_00000000")!) + + XCTAssertTrue(UInt256(hex: "00000000_00d321ae_f0000000_f0000000_f0000000_f0000000_f0000000_f0000000")! + < UInt256(hex: "00000000_00d321af_00000000_00000000_00000000_00000000_00000000_00000000")!) + + XCTAssertTrue(UInt256(hex: "00000000_00000000_0000eefe_f0000000_f0000000_f0000000_f0000000_f0000000")! + < UInt256(hex: "00000000_00000000_0000efed_00000000_00000000_00000000_00000000_00000000")!) + + XCTAssertTrue(UInt256(hex: "00000000_00000000_00000000_01020304_0000000f_0000000f_0000000f_0000000f")! + < UInt256(hex: "00000000_00000000_00000000_0e000000_00000000_00000000_00000000_00000000")!) + + XCTAssertTrue(UInt256(hex: "00000000_00000000_00000000_00000000_d5632433_0000000f_0000000f_0000000f")! + < UInt256(hex: "00000000_00000000_00000000_00000000_f1000000_00000000_00000000_00000000")!) + + XCTAssertTrue(UInt256(hex: "00000000_00000000_00000000_00000000_00000000_21234567_0000000f_0000000f")! + < UInt256(hex: "00000000_00000000_00000000_00000000_00000000_31234567_0000000f_00000000")!) + + XCTAssertTrue(UInt256(hex: "00000000_00000000_00000000_00000000_00000000_00000000_1200000f_0000000f")! + < UInt256(hex: "00000000_00000000_00000000_00000000_00000000_00000000_1300000f_00000000")!) + } + +} diff --git a/Tests/BitcoinKitTests/UInt32MathTests.swift b/Tests/BitcoinKitTests/UInt32MathTests.swift new file mode 100644 index 00000000..dd57f85e --- /dev/null +++ b/Tests/BitcoinKitTests/UInt32MathTests.swift @@ -0,0 +1,43 @@ +// +// UInt32+MathTests.swift +// +// Copyright © 2018 pebble8888 All rights reserved. +// + +import XCTest +@testable import BitcoinKit + +class UInt32MathTests: XCTestCase { + + override func setUp() { + super.setUp() + } + + override func tearDown() { + super.tearDown() + } + + func test1() { + XCTAssertEqual(ceil_log2(0), 0) + XCTAssertEqual(ceil_log2(1), 0) + XCTAssertEqual(ceil_log2(2), 1) + XCTAssertEqual(ceil_log2(3), 2) + XCTAssertEqual(ceil_log2(4), 2) + XCTAssertEqual(ceil_log2(5), 3) + XCTAssertEqual(ceil_log2(6), 3) + XCTAssertEqual(ceil_log2(7), 3) + XCTAssertEqual(ceil_log2(8), 3) + XCTAssertEqual(ceil_log2(9), 4) + XCTAssertEqual(ceil_log2(10), 4) + XCTAssertEqual(ceil_log2(11), 4) + XCTAssertEqual(ceil_log2(12), 4) + XCTAssertEqual(ceil_log2(13), 4) + XCTAssertEqual(ceil_log2(14), 4) + XCTAssertEqual(ceil_log2(15), 4) + XCTAssertEqual(ceil_log2(16), 4) + XCTAssertEqual(ceil_log2(17), 5) + + XCTAssertEqual(ceil_log2(UInt32.max-1), 32) + XCTAssertEqual(ceil_log2(UInt32.max), 32) + } +} From 368580bea154022dc68307855b203842cac04cf4 Mon Sep 17 00:00:00 2001 From: pebble8888 Date: Tue, 11 Sep 2018 20:21:27 +0900 Subject: [PATCH 2/7] modify if to guard --- Sources/BitcoinKit/Core/ProofOfWork.swift | 6 +++--- Sources/BitcoinKit/Networking/PeerGroup.swift | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Sources/BitcoinKit/Core/ProofOfWork.swift b/Sources/BitcoinKit/Core/ProofOfWork.swift index bb038042..d527d330 100644 --- a/Sources/BitcoinKit/Core/ProofOfWork.swift +++ b/Sources/BitcoinKit/Core/ProofOfWork.swift @@ -17,11 +17,11 @@ class ProofOfWork { // invalid bits return false } - if target == UInt256.zero { + guard target != UInt256.zero else { // invalid zero target return false } - if target > maxProofOfWork { + guard target <= maxProofOfWork else { // too high target return false } @@ -29,7 +29,7 @@ class ProofOfWork { // invalid blockHash data length return false } - if arith_hash > target { + guard arith_hash <= target else { // insufficient proof of work return false } diff --git a/Sources/BitcoinKit/Networking/PeerGroup.swift b/Sources/BitcoinKit/Networking/PeerGroup.swift index 57577487..ea8cf462 100644 --- a/Sources/BitcoinKit/Networking/PeerGroup.swift +++ b/Sources/BitcoinKit/Networking/PeerGroup.swift @@ -103,7 +103,7 @@ public class PeerGroup: PeerDelegate { } public func peer(_ peer: Peer, didReceiveMerkleBlockMessage message: MerkleBlockMessage, hash: Data) { - if !ProofOfWork.isValidProofOfWork(blockHash: hash, bits: message.bits) { + guard ProofOfWork.isValidProofOfWork(blockHash: hash, bits: message.bits) else { print("insufficient proof of work!") return } From 89c742efac2f339a25c773921121cc484f2d3eed Mon Sep 17 00:00:00 2001 From: pebble8888 Date: Fri, 14 Sep 2018 19:46:32 +0900 Subject: [PATCH 3/7] add license comment --- Sources/BitcoinKit/Core/Math.swift | 23 +++++++++++++++++-- Sources/BitcoinKit/Core/MerkleTree.swift | 21 ++++++++++++++++- Sources/BitcoinKit/Core/ProofOfWork.swift | 21 ++++++++++++++++- Sources/BitcoinKit/Core/UInt256+Bitcoin.swift | 23 +++++++++++++++++-- Sources/BitcoinKit/Core/UInt256.swift | 21 ++++++++++++++++- Sources/BitcoinKit/Core/UInt32+Utility.swift | 21 ++++++++++++++++- Tests/BitcoinKitTests/ProofOfWorkTests.swift | 21 ++++++++++++++++- .../BitcoinKitTests/SerializationTests.swift | 21 ++++++++++++++++- .../UInt256+BitcoinTests.swift | 21 ++++++++++++++++- Tests/BitcoinKitTests/UInt256Tests.swift | 21 ++++++++++++++++- Tests/BitcoinKitTests/UInt32MathTests.swift | 23 +++++++++++++++++-- 11 files changed, 223 insertions(+), 14 deletions(-) diff --git a/Sources/BitcoinKit/Core/Math.swift b/Sources/BitcoinKit/Core/Math.swift index 2e666c89..9cc5ba81 100644 --- a/Sources/BitcoinKit/Core/Math.swift +++ b/Sources/BitcoinKit/Core/Math.swift @@ -1,8 +1,27 @@ // -// UInt32+Math.swift +// Math.swift // -// Copyright © 2018 pebble8888 All rights reserved. +// Copyright © 2018 pebble8888 +// Copyright © 2018 BitcoinKit developers +/// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: // +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +/// import Foundation diff --git a/Sources/BitcoinKit/Core/MerkleTree.swift b/Sources/BitcoinKit/Core/MerkleTree.swift index b3e48fba..58ba0c09 100644 --- a/Sources/BitcoinKit/Core/MerkleTree.swift +++ b/Sources/BitcoinKit/Core/MerkleTree.swift @@ -1,7 +1,26 @@ // // MerkleTree.swift // -// Copyright © 2018 pebble8888 All rights reserved. +// Copyright © 2018 pebble8888 +// Copyright © 2018 BitcoinKit developers +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. // import Foundation diff --git a/Sources/BitcoinKit/Core/ProofOfWork.swift b/Sources/BitcoinKit/Core/ProofOfWork.swift index d527d330..4c1bd443 100644 --- a/Sources/BitcoinKit/Core/ProofOfWork.swift +++ b/Sources/BitcoinKit/Core/ProofOfWork.swift @@ -1,7 +1,26 @@ // // ProofOfWork.swift // -// Copyright © 2018 pebble8888 All rights reserved. +// Copyright © 2018 pebble8888 +// Copyright © 2018 BitcoinKit developers +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. // import Foundation diff --git a/Sources/BitcoinKit/Core/UInt256+Bitcoin.swift b/Sources/BitcoinKit/Core/UInt256+Bitcoin.swift index b82e3be2..4c578fe9 100644 --- a/Sources/BitcoinKit/Core/UInt256+Bitcoin.swift +++ b/Sources/BitcoinKit/Core/UInt256+Bitcoin.swift @@ -1,7 +1,26 @@ // -// UInt256+bitcoin.swift +// UInt256+Bitcoin.swift // -// Copyright © 2018 pebble8888 All rights reserved. +// Copyright © 2018 pebble8888 +// Copyright © 2018 BitcoinKit developers +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. // import Foundation diff --git a/Sources/BitcoinKit/Core/UInt256.swift b/Sources/BitcoinKit/Core/UInt256.swift index d6b2586d..46fab3bd 100644 --- a/Sources/BitcoinKit/Core/UInt256.swift +++ b/Sources/BitcoinKit/Core/UInt256.swift @@ -1,7 +1,26 @@ // // UInt256.swift // -// Copyright © 2018 pebble8888 All rights reserved. +// Copyright © 2018 pebble8888 +// Copyright © 2018 BitcoinKit developers +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. // import Foundation diff --git a/Sources/BitcoinKit/Core/UInt32+Utility.swift b/Sources/BitcoinKit/Core/UInt32+Utility.swift index 2fd7ee33..262a0430 100644 --- a/Sources/BitcoinKit/Core/UInt32+Utility.swift +++ b/Sources/BitcoinKit/Core/UInt32+Utility.swift @@ -1,7 +1,26 @@ // // UInt32+Utility.swift // -// Copyright © 2018 pebble8888 All rights reserved. +// Copyright © 2018 pebble8888 +// Copyright © 2018 BitcoinKit developers +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. // import Foundation diff --git a/Tests/BitcoinKitTests/ProofOfWorkTests.swift b/Tests/BitcoinKitTests/ProofOfWorkTests.swift index bb8b21a0..a8f2ae06 100644 --- a/Tests/BitcoinKitTests/ProofOfWorkTests.swift +++ b/Tests/BitcoinKitTests/ProofOfWorkTests.swift @@ -1,7 +1,26 @@ // // ProofOfWorkTests.swift // -// Copyright © 2018 pebble8888 All rights reserved. +// Copyright © 2018 pebble8888 +// Copyright © 2018 BitcoinKit developers +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. // import XCTest diff --git a/Tests/BitcoinKitTests/SerializationTests.swift b/Tests/BitcoinKitTests/SerializationTests.swift index da08fc1b..7b369479 100644 --- a/Tests/BitcoinKitTests/SerializationTests.swift +++ b/Tests/BitcoinKitTests/SerializationTests.swift @@ -1,7 +1,26 @@ // // SerializationTests.swift // -// Copyright © 2018 pebble8888 All rights reserved. +// Copyright © 2018 pebble8888 +// Copyright © 2018 BitcoinKit developers +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. // import XCTest diff --git a/Tests/BitcoinKitTests/UInt256+BitcoinTests.swift b/Tests/BitcoinKitTests/UInt256+BitcoinTests.swift index b99ab116..4062685e 100644 --- a/Tests/BitcoinKitTests/UInt256+BitcoinTests.swift +++ b/Tests/BitcoinKitTests/UInt256+BitcoinTests.swift @@ -1,7 +1,26 @@ // // UInt256+BitcoinTests.swift // -// Copyright © 2018 pebble8888 All rights reserved. +// Copyright © 2018 pebble8888 +// Copyright © 2018 BitcoinKit developers +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. // import XCTest diff --git a/Tests/BitcoinKitTests/UInt256Tests.swift b/Tests/BitcoinKitTests/UInt256Tests.swift index 957e57a6..f888fbdd 100644 --- a/Tests/BitcoinKitTests/UInt256Tests.swift +++ b/Tests/BitcoinKitTests/UInt256Tests.swift @@ -1,7 +1,26 @@ // // UInt256Tests.swift // -// Copyright © 2018 pebble8888 All rights reserved. +// Copyright © 2018 pebble8888 +// Copyright © 2018 BitcoinKit developers +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. // import XCTest diff --git a/Tests/BitcoinKitTests/UInt32MathTests.swift b/Tests/BitcoinKitTests/UInt32MathTests.swift index dd57f85e..50cfcfe9 100644 --- a/Tests/BitcoinKitTests/UInt32MathTests.swift +++ b/Tests/BitcoinKitTests/UInt32MathTests.swift @@ -1,7 +1,26 @@ // -// UInt32+MathTests.swift +// UInt32MathTests.swift // -// Copyright © 2018 pebble8888 All rights reserved. +// Copyright © 2018 pebble8888 +// Copyright © 2018 BitcoinKit developers +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. // import XCTest From 9c7c89c8887cbb87186da4c4f710d17caff542ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=97=A4=E7=94=B0=E5=93=B2=E5=8F=B2?= Date: Wed, 26 Sep 2018 20:00:19 +0900 Subject: [PATCH 4/7] :recycle: update with Lint --- BitcoinKit.xcodeproj/project.pbxproj | 10 +-- Sources/BitcoinKit/Core/Math.swift | 2 +- Sources/BitcoinKit/Core/MerkleTree.swift | 25 +++--- Sources/BitcoinKit/Core/ProofOfWork.swift | 2 +- Sources/BitcoinKit/Core/UInt256+Bitcoin.swift | 2 +- Sources/BitcoinKit/Core/UInt256.swift | 81 +++++++++---------- Sources/BitcoinKit/Core/UInt32+Utility.swift | 2 +- 7 files changed, 55 insertions(+), 69 deletions(-) diff --git a/BitcoinKit.xcodeproj/project.pbxproj b/BitcoinKit.xcodeproj/project.pbxproj index 19a51b80..9f925113 100644 --- a/BitcoinKit.xcodeproj/project.pbxproj +++ b/BitcoinKit.xcodeproj/project.pbxproj @@ -59,6 +59,7 @@ 0C2375A52132507B00DB2872 /* MessageSerializerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C2375A32132501700DB2872 /* MessageSerializerTests.swift */; }; 0C2CB94D211FAD320087A8EB /* OP_BIN2NUM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C2CB94C211FAD320087A8EB /* OP_BIN2NUM.swift */; }; 0C4132EF210EFD1700906E4A /* OP_SWAP.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C4132EE210EFD1700906E4A /* OP_SWAP.swift */; }; + 0C61BF51215B988A001415CA /* Encoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C61BF50215B988A001415CA /* Encoding.swift */; }; 0C66CD032125425D0049DB89 /* OP_INVERT.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C66CD022125425D0049DB89 /* OP_INVERT.swift */; }; 0C66CD05212542660049DB89 /* OP_AND.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C66CD04212542660049DB89 /* OP_AND.swift */; }; 0C66CD07212542730049DB89 /* OP_OR.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0C66CD06212542730049DB89 /* OP_OR.swift */; }; @@ -74,7 +75,6 @@ 147494D6201F9A29006D1CF8 /* BitcoinKitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 147494D5201F9A29006D1CF8 /* BitcoinKitTests.swift */; }; 147494D8201F9A29006D1CF8 /* BitcoinKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 147494CA201F9A29006D1CF8 /* BitcoinKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; 147494E4201F9B85006D1CF8 /* Crypto.swift in Sources */ = {isa = PBXBuildFile; fileRef = 147494E3201F9B85006D1CF8 /* Crypto.swift */; }; - 147494E6201F9BF0006D1CF8 /* Encoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 147494E5201F9BEF006D1CF8 /* Encoding.swift */; }; 147494EC201F9E4F006D1CF8 /* Network.swift in Sources */ = {isa = PBXBuildFile; fileRef = 147494EB201F9E4F006D1CF8 /* Network.swift */; }; 147494EE201FADAC006D1CF8 /* MurmurHash.swift in Sources */ = {isa = PBXBuildFile; fileRef = 147494ED201FADAC006D1CF8 /* MurmurHash.swift */; }; 147494F0201FAE30006D1CF8 /* Serialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 147494EF201FAE30006D1CF8 /* Serialization.swift */; }; @@ -292,6 +292,7 @@ 0C2375A32132501700DB2872 /* MessageSerializerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageSerializerTests.swift; sourceTree = ""; }; 0C2CB94C211FAD320087A8EB /* OP_BIN2NUM.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OP_BIN2NUM.swift; sourceTree = ""; }; 0C4132EE210EFD1700906E4A /* OP_SWAP.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OP_SWAP.swift; sourceTree = ""; }; + 0C61BF50215B988A001415CA /* Encoding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Encoding.swift; path = Keys/Encoding.swift; sourceTree = ""; }; 0C66CD022125425D0049DB89 /* OP_INVERT.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OP_INVERT.swift; sourceTree = ""; }; 0C66CD04212542660049DB89 /* OP_AND.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OP_AND.swift; sourceTree = ""; }; 0C66CD06212542730049DB89 /* OP_OR.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OP_OR.swift; sourceTree = ""; }; @@ -310,7 +311,6 @@ 147494D5201F9A29006D1CF8 /* BitcoinKitTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BitcoinKitTests.swift; sourceTree = ""; }; 147494D7201F9A29006D1CF8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 147494E3201F9B85006D1CF8 /* Crypto.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Crypto.swift; sourceTree = ""; }; - 147494E5201F9BEF006D1CF8 /* Encoding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Encoding.swift; sourceTree = ""; }; 147494EB201F9E4F006D1CF8 /* Network.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Network.swift; sourceTree = ""; }; 147494ED201FADAC006D1CF8 /* MurmurHash.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MurmurHash.swift; sourceTree = ""; }; 147494EF201FAE30006D1CF8 /* Serialization.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Serialization.swift; sourceTree = ""; }; @@ -649,7 +649,7 @@ 1482B5E32026F2580098B612 /* WordList.swift */, 14839A7B202F79F900A6CB34 /* PaymentURI.swift */, 147494E3201F9B85006D1CF8 /* Crypto.swift */, - 147494E5201F9BEF006D1CF8 /* Encoding.swift */, + 0C61BF50215B988A001415CA /* Encoding.swift */, A29721F7211B2497007228D5 /* Math.swift */, A246ED0F2118621B0000418D /* MerkleTree.swift */, A2B7A34D2125464400764AE9 /* ProofOfWork.swift */, @@ -902,7 +902,6 @@ 1482B5E7202721FF0098B612 /* HDPrivateKey.swift */, 1482B5E920273B8A0098B612 /* HDPublicKey.swift */, 14CDC3892021881A00C01556 /* Address.swift */, - 147494E5201F9BEF006D1CF8 /* Encoding.swift */, 294991FF20F227EB00D078B6 /* VersionByte.swift */, 297DB97220EB12E60077EEEE /* AddressType.swift */, 297DB97420EB13320077EEEE /* AddressFactory.swift */, @@ -1068,7 +1067,6 @@ 14839A9D202FE72600A6CB34 /* TransactionOutPoint.swift in Sources */, 2933014D214FCE150028946B /* TransactionHistoryProvider.swift in Sources */, 0C1DE155211D787100FE8E43 /* OP_TOTALSTACK.swift in Sources */, - 147494E6201F9BF0006D1CF8 /* Encoding.swift in Sources */, 2949920220F228B400D078B6 /* UnspentTransaction.swift in Sources */, 0C0900442116BA8F0077E9BC /* OP_RSHIFT.swift in Sources */, 14839A7F202FE58800A6CB34 /* VersionMessage.swift in Sources */, @@ -1159,6 +1157,7 @@ 29248EEF2104B64E00CC9051 /* ScriptChunkHelper.swift in Sources */, 14839A85202FE60E00A6CB34 /* InventoryMessage.swift in Sources */, 14839AA7202FE7C700A6CB34 /* VarInt.swift in Sources */, + 0C61BF51215B988A001415CA /* Encoding.swift in Sources */, 29E1ED73210ECD35007F4627 /* OP_CHECKMULTISIG.swift in Sources */, 29290B99210AF88400D2BE78 /* OP_EQUALVERIFY.swift in Sources */, 294DDE47211B322000B7F645 /* OP_ELSE.swift in Sources */, @@ -1255,7 +1254,6 @@ files = ( 147494D6201F9A29006D1CF8 /* BitcoinKitTests.swift in Sources */, A2DE5110212AFCF200F54EA0 /* UInt256+BitcoinTests.swift in Sources */, - 147494D6201F9A29006D1CF8 /* BitcoinCashKitTests.swift in Sources */, CFA290742102B650001A1BAB /* ScriptMachineTests.swift in Sources */, 6E20AECB2112C434008A9810 /* HDPrivateKeyTests.swift in Sources */, 6E20AED52112C8F9008A9810 /* BloomFilterTests.swift in Sources */, diff --git a/Sources/BitcoinKit/Core/Math.swift b/Sources/BitcoinKit/Core/Math.swift index 9cc5ba81..b5e30149 100644 --- a/Sources/BitcoinKit/Core/Math.swift +++ b/Sources/BitcoinKit/Core/Math.swift @@ -28,7 +28,7 @@ import Foundation func ceil_log2(_ x: UInt32) -> UInt32 { if x == 0 { return 0 } var xx = x - var r: UInt32 = (xx & (xx-1)) != 0 ? 1 : 0 + var r: UInt32 = (xx & (xx - 1)) != 0 ? 1 : 0 while true { xx >>= 1 if xx == 0 { break } diff --git a/Sources/BitcoinKit/Core/MerkleTree.swift b/Sources/BitcoinKit/Core/MerkleTree.swift index 58ba0c09..42523ff7 100644 --- a/Sources/BitcoinKit/Core/MerkleTree.swift +++ b/Sources/BitcoinKit/Core/MerkleTree.swift @@ -34,18 +34,16 @@ struct MerkleTree { case invalidNumberOfFlags case nullHash } - - static func buildMerkleRoot(numberOfHashes: UInt32, hashes: [Data], numberOfFlags: UInt32, flags: [UInt8], - totalTransactions: UInt32) throws -> Data - { + + static func buildMerkleRoot(numberOfHashes: UInt32, hashes: [Data], numberOfFlags: UInt32, flags: [UInt8], totalTransactions: UInt32) throws -> Data { if numberOfHashes != hashes.count { throw MerkleError.invalidNumberOfHashes } - if flags.count < numberOfFlags/8 { + if flags.count < numberOfFlags / 8 { throw MerkleError.invalidNumberOfFlags } let parents: [Bool] = (0 ..< Int(numberOfFlags)).compactMap({ - return (flags[$0/8] & UInt8(1 << ($0 % 8))) != 0 + return (flags[$0 / 8] & UInt8(1 << ($0 % 8))) != 0 }) let maxdepth: UInt = UInt(ceil_log2(totalTransactions)) var hashIterator = hashes.makeIterator() @@ -54,27 +52,26 @@ struct MerkleTree { guard let h = root.hash else { throw MerkleError.nullHash } return h } - + struct PartialMerkleTree { var hash: Data? // zero size if depth is maxdepth // leaf[0]: left, leaf[1]: right var leaf: [PartialMerkleTree] = [] - init(hash: Data, leafL: PartialMerkleTree, leafR: PartialMerkleTree){ + init(hash: Data, leafL: PartialMerkleTree, leafR: PartialMerkleTree) { self.hash = hash leaf.append(leafL) leaf.append(leafR) } - init(hash: Data){ + init(hash: Data) { self.hash = hash } } - + private static func buildPartialMerkleTree( - hashIterator: inout IndexingIterator>, - parentIterator: inout IndexingIterator>, - depth: UInt, maxdepth: UInt) throws -> PartialMerkleTree - { + hashIterator: inout IndexingIterator<[Data]>, + parentIterator: inout IndexingIterator<[Bool]>, + depth: UInt, maxdepth: UInt) throws -> PartialMerkleTree { guard let parent = parentIterator.next() else { throw MerkleError.noEnoughParent } if !parent || maxdepth <= depth { // leaf diff --git a/Sources/BitcoinKit/Core/ProofOfWork.swift b/Sources/BitcoinKit/Core/ProofOfWork.swift index 4c1bd443..cf91270f 100644 --- a/Sources/BitcoinKit/Core/ProofOfWork.swift +++ b/Sources/BitcoinKit/Core/ProofOfWork.swift @@ -27,7 +27,7 @@ import Foundation class ProofOfWork { static let maxProofOfWork: UInt256 - = UInt256(data: Data(hex:"00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff")!)! + = UInt256(data: Data(hex: "00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff")!)! static func isValidProofOfWork(blockHash: Data, bits: UInt32) -> Bool { let target: UInt256 do { diff --git a/Sources/BitcoinKit/Core/UInt256+Bitcoin.swift b/Sources/BitcoinKit/Core/UInt256+Bitcoin.swift index 4c578fe9..ef019f3b 100644 --- a/Sources/BitcoinKit/Core/UInt256+Bitcoin.swift +++ b/Sources/BitcoinKit/Core/UInt256+Bitcoin.swift @@ -26,7 +26,7 @@ import Foundation extension UInt256 { - public enum CompactError: Error { + public enum CompactError: Error { case negative, overflow } // bitcoin "compact" format diff --git a/Sources/BitcoinKit/Core/UInt256.swift b/Sources/BitcoinKit/Core/UInt256.swift index 46fab3bd..0ab50ab9 100644 --- a/Sources/BitcoinKit/Core/UInt256.swift +++ b/Sources/BitcoinKit/Core/UInt256.swift @@ -33,28 +33,27 @@ struct UInt256 { public static var max: UInt256 { return UInt256(UInt64.max, UInt64.max, UInt64.max, UInt64.max) } - public static var bitWidth: Int { get { return 256 } } + public static var bitWidth: Int { return 256 } public static let byteWidth = UInt256.bitWidth / 8 static let elementCount = byteWidth / 8 - + // e0 is lowest digit (UInt64 value is LittleEndian) // e3 is highest digit (UInt64 value is LittleEndian) private var e0: UInt64 private var e1: UInt64 private var e2: UInt64 private var e3: UInt64 - + public static let zero = UInt256() - + init() { e0 = 0 e1 = 0 e2 = 0 e3 = 0 } - - init(_ e0: UInt64, _ e1: UInt64, _ e2: UInt64, _ e3: UInt64) - { + + init(_ e0: UInt64, _ e1: UInt64, _ e2: UInt64, _ e3: UInt64) { self.e0 = e0 self.e1 = e1 self.e2 = e2 @@ -71,7 +70,7 @@ struct UInt256 { e2 = data[16..<24].to(type: UInt64.self) e3 = data[24..<32].to(type: UInt64.self) } - + // hex: MSB representation // "_" is ignored in parsing // UInt256(hex: "00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000001") @@ -82,25 +81,25 @@ struct UInt256 { guard let data = Data(hex: h)?.reversed() else { return nil } self.init(data: Data(data)) } - + public init(_ val: UInt) { // set to lowest digit self = UInt256(UInt64(val), 0, 0, 0) } - - public init(_ val: UInt64){ + + public init(_ val: UInt64) { self = UInt256(val, 0, 0, 0) } - - public init(_ val: UInt32){ + + public init(_ val: UInt32) { self = UInt256(UInt64(val)) } - - public init(_ val: UInt16){ + + public init(_ val: UInt16) { self = UInt256(UInt64(val)) } - - public init(_ val: UInt8){ + + public init(_ val: UInt8) { self = UInt256(UInt64(val)) } } @@ -111,23 +110,17 @@ extension UInt256: CustomDebugStringConvertible { } } -extension UInt256 : Equatable { +extension UInt256: Equatable { public static func == (lhs: UInt256, rhs: UInt256) -> Bool { - if lhs.e0 != rhs.e0 { return false } - else if lhs.e1 != rhs.e1 { return false } - else if lhs.e2 != rhs.e2 { return false } - else if lhs.e3 != rhs.e3 { return false } + if lhs.e0 != rhs.e0 { return false } else if lhs.e1 != rhs.e1 { return false } else if lhs.e2 != rhs.e2 { return false } else if lhs.e3 != rhs.e3 { return false } return true } } -extension UInt256 : Comparable { +extension UInt256: Comparable { public static func < (lhs: UInt256, rhs: UInt256) -> Bool { // compare higest digit at first - if lhs.e3 != rhs.e3 { return lhs.e3 < rhs.e3 } - else if lhs.e2 != rhs.e2 { return lhs.e2 < rhs.e2 } - else if lhs.e1 != rhs.e1 { return lhs.e1 < rhs.e1 } - else if lhs.e0 != rhs.e0 { return lhs.e0 < rhs.e0 } + if lhs.e3 != rhs.e3 { return lhs.e3 < rhs.e3 } else if lhs.e2 != rhs.e2 { return lhs.e2 < rhs.e2 } else if lhs.e1 != rhs.e1 { return lhs.e1 < rhs.e1 } else if lhs.e0 != rhs.e0 { return lhs.e0 < rhs.e0 } // a < a is always false (Irreflexivity) return false } @@ -136,7 +129,7 @@ extension UInt256 : Comparable { extension UInt64 { // MSB representation public var hex: String { - return String(format:"%016lx", self) + return String(format: "%016lx", self) } } @@ -155,13 +148,12 @@ extension UInt256 { } protocol BitShiftOperator { - static func >> (lhs: Self, rhs: RHS) -> Self where RHS : UnsignedInteger - static func << (lhs: Self, rhs: RHS) -> Self where RHS : UnsignedInteger + static func >> (lhs: Self, rhs: RHS) -> Self where RHS: UnsignedInteger + static func << (lhs: Self, rhs: RHS) -> Self where RHS: UnsignedInteger } extension UInt256: BitShiftOperator { - public static func >> (lhs: UInt256, rhs: RHS) -> UInt256 where RHS : UnsignedInteger - { + public static func >> (lhs: UInt256, rhs: RHS) -> UInt256 where RHS: UnsignedInteger { if rhs < 64 { var v = UInt256() let mask = bitValue(bit: UInt(rhs)) @@ -173,36 +165,35 @@ extension UInt256: BitShiftOperator { return v } else if rhs < 128 { var v = UInt256() - let mask = bitValue(bit: UInt(rhs-64)) + let mask = bitValue(bit: UInt(rhs - 64)) let shift = 128 - rhs v.e3 = 0 - v.e2 = (lhs.e3 >> (rhs-64)) - v.e1 = (lhs.e2 >> (rhs-64)) + ((lhs.e3 & mask) << shift) - v.e0 = (lhs.e1 >> (rhs-64)) + ((lhs.e2 & mask) << shift) + v.e2 = (lhs.e3 >> (rhs - 64)) + v.e1 = (lhs.e2 >> (rhs - 64)) + ((lhs.e3 & mask) << shift) + v.e0 = (lhs.e1 >> (rhs - 64)) + ((lhs.e2 & mask) << shift) return v } else if rhs < 192 { var v = UInt256() - let mask = bitValue(bit: UInt(rhs-128)) + let mask = bitValue(bit: UInt(rhs - 128)) let shift = 192 - rhs v.e3 = 0 v.e2 = 0 - v.e1 = (lhs.e3 >> (rhs-128)) - v.e0 = (lhs.e2 >> (rhs-128)) + ((lhs.e3 & mask) << shift) + v.e1 = (lhs.e3 >> (rhs - 128)) + v.e0 = (lhs.e2 >> (rhs - 128)) + ((lhs.e3 & mask) << shift) return v } else if rhs < 256 { var v = UInt256() v.e3 = 0 v.e2 = 0 v.e1 = 0 - v.e0 = (lhs.e3 >> (rhs-192)) + v.e0 = (lhs.e3 >> (rhs - 192)) return v } else { return UInt256.zero } } - - public static func << (lhs: UInt256, rhs: RHS) -> UInt256 where RHS : UnsignedInteger - { + + public static func << (lhs: UInt256, rhs: RHS) -> UInt256 where RHS: UnsignedInteger { if rhs < 64 { var v = UInt256() let rev = rhs @@ -244,8 +235,8 @@ extension UInt256: BitShiftOperator { } } -fileprivate func bitValue(bit: UInt) -> UInt64 { - var v:UInt64 = 0 +private func bitValue(bit: UInt) -> UInt64 { + var v: UInt64 = 0 for i in 0 ..< bit { v += (1 << i) } diff --git a/Sources/BitcoinKit/Core/UInt32+Utility.swift b/Sources/BitcoinKit/Core/UInt32+Utility.swift index 262a0430..05c36db8 100644 --- a/Sources/BitcoinKit/Core/UInt32+Utility.swift +++ b/Sources/BitcoinKit/Core/UInt32+Utility.swift @@ -27,6 +27,6 @@ import Foundation extension UInt32 { public var hex: String { - return String(format:"%08x", self) + return String(format: "%08x", self) } } From ca10bf0513ae5ebda170ea943d0714ffa3e86c1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=97=A4=E7=94=B0=E5=93=B2=E5=8F=B2?= Date: Wed, 26 Sep 2018 20:04:45 +0900 Subject: [PATCH 5/7] :recycle: rename tests --- Tests/BitcoinKitTests/SerializationTests.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/BitcoinKitTests/SerializationTests.swift b/Tests/BitcoinKitTests/SerializationTests.swift index 7b369479..8cabef55 100644 --- a/Tests/BitcoinKitTests/SerializationTests.swift +++ b/Tests/BitcoinKitTests/SerializationTests.swift @@ -36,14 +36,14 @@ class SerializationTests: XCTestCase { super.tearDown() } - func test1() { + func testUInt32toHex() { let d = Data(bytes: [1, 2, 3, 4]) let i: UInt32 = d.to(type: UInt32.self) XCTAssertEqual(i.hex, "04030201") XCTAssertEqual(i, 0x04030201) } - func test2() { + func testDataToUInt256() { let d = Data(bytes: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]) let i: UInt256 = d.to(type: UInt256.self) XCTAssertEqual(i.hex, "0200000000000000000000000000000000000000000000000000000000000001") From 7ed9aef2a3d0bf8e90f764d0de321795b0c5cf47 Mon Sep 17 00:00:00 2001 From: Shun Usami Date: Thu, 12 Sep 2019 13:24:55 +0900 Subject: [PATCH 6/7] =?UTF-8?q?=F0=9F=90=9B=20Fix=20Integer=20bug=20on=203?= =?UTF-8?q?2=20bit=20devices?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- BitcoinKit.xcodeproj/project.pbxproj | 4 -- Sources/BitcoinKit/Core/UInt256.swift | 4 +- .../BitcoinKitTests/SerializationTests.swift | 9 +++- .../UInt256+BitcoinTests.swift | 48 +++++++++---------- 4 files changed, 35 insertions(+), 30 deletions(-) diff --git a/BitcoinKit.xcodeproj/project.pbxproj b/BitcoinKit.xcodeproj/project.pbxproj index c8872b3e..3950ec89 100644 --- a/BitcoinKit.xcodeproj/project.pbxproj +++ b/BitcoinKit.xcodeproj/project.pbxproj @@ -161,7 +161,6 @@ 2949920220F228B400D078B6 /* UnspentTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2949920120F228B400D078B6 /* UnspentTransaction.swift */; }; 2949920420F22A1500D078B6 /* TestHelpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2949920320F22A1500D078B6 /* TestHelpers.swift */; }; 2949920620F22DCA00D078B6 /* UnsignedTransaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2949920520F22DCA00D078B6 /* UnsignedTransaction.swift */; }; - 294D6CB6215A124700B75928 /* SerializationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 294D6CB5215A124700B75928 /* SerializationTests.swift */; }; 294DDE32211A05D200B7F645 /* OP_RETURN.swift in Sources */ = {isa = PBXBuildFile; fileRef = 294DDE31211A05D200B7F645 /* OP_RETURN.swift */; }; 294DDE3B211B31B100B7F645 /* OP_NOP.swift in Sources */ = {isa = PBXBuildFile; fileRef = 294DDE3A211B31B100B7F645 /* OP_NOP.swift */; }; 294DDE3D211B31C100B7F645 /* OP_VER.swift in Sources */ = {isa = PBXBuildFile; fileRef = 294DDE3C211B31C100B7F645 /* OP_VER.swift */; }; @@ -402,7 +401,6 @@ 2949920120F228B400D078B6 /* UnspentTransaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnspentTransaction.swift; sourceTree = ""; }; 2949920320F22A1500D078B6 /* TestHelpers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestHelpers.swift; sourceTree = ""; }; 2949920520F22DCA00D078B6 /* UnsignedTransaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnsignedTransaction.swift; sourceTree = ""; }; - 294D6CB5215A124700B75928 /* SerializationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SerializationTests.swift; sourceTree = ""; }; 294DDE31211A05D200B7F645 /* OP_RETURN.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OP_RETURN.swift; sourceTree = ""; }; 294DDE3A211B31B100B7F645 /* OP_NOP.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OP_NOP.swift; sourceTree = ""; }; 294DDE3C211B31C100B7F645 /* OP_VER.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OP_VER.swift; sourceTree = ""; }; @@ -614,7 +612,6 @@ A2DAA5F8211F2C93009DAB7B /* SerializationTests.swift */, A2DE510F212AFCF200F54EA0 /* UInt256+BitcoinTests.swift */, A2E11230212C400A00A0A40A /* ProofOfWorkTests.swift */, - 294D6CB5215A124700B75928 /* SerializationTests.swift */, ); name = BitcoinKitTests; path = Tests/BitcoinKitTests; @@ -1299,7 +1296,6 @@ 29F5D1E02110495F007DA3BF /* OpCodeTests.swift in Sources */, 6E20AEC92112C31A008A9810 /* LegacyAddressTests.swift in Sources */, 6E20AED12112C6AA008A9810 /* PaymentURITests.swift in Sources */, - 294D6CB6215A124700B75928 /* SerializationTests.swift in Sources */, CF432AF220F0CF9100AD4020 /* Base58Tests.swift in Sources */, A2DAA5F9211F2C93009DAB7B /* SerializationTests.swift in Sources */, 2949920420F22A1500D078B6 /* TestHelpers.swift in Sources */, diff --git a/Sources/BitcoinKit/Core/UInt256.swift b/Sources/BitcoinKit/Core/UInt256.swift index 0ab50ab9..0cd00014 100644 --- a/Sources/BitcoinKit/Core/UInt256.swift +++ b/Sources/BitcoinKit/Core/UInt256.swift @@ -129,7 +129,9 @@ extension UInt256: Comparable { extension UInt64 { // MSB representation public var hex: String { - return String(format: "%016lx", self) + let high: UInt64 = (self & 0xffffffff00000000) >> 32 + let low: UInt64 = self & 0x00000000ffffffff + return String(format: "%08x", high) + String(format: "%08x", low) } } diff --git a/Tests/BitcoinKitTests/SerializationTests.swift b/Tests/BitcoinKitTests/SerializationTests.swift index 2852a3d9..2e0a84bb 100644 --- a/Tests/BitcoinKitTests/SerializationTests.swift +++ b/Tests/BitcoinKitTests/SerializationTests.swift @@ -40,7 +40,14 @@ class SerializationTests: XCTestCase { XCTAssertEqual(i.hex, "04030201") XCTAssertEqual(i, 0x04030201) } - + + func testUInt64toHex() { + let d = Data(bytes: [1, 2, 3, 4, 5, 6, 7, 8]) + let i: UInt64 = d.to(type: UInt64.self) + XCTAssertEqual(i.hex, "0807060504030201") + XCTAssertEqual(i, 0x0807060504030201) + } + func testDataToUInt256() { let d = Data(bytes: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2]) let i: UInt256 = d.to(type: UInt256.self) diff --git a/Tests/BitcoinKitTests/UInt256+BitcoinTests.swift b/Tests/BitcoinKitTests/UInt256+BitcoinTests.swift index 4062685e..a938895b 100644 --- a/Tests/BitcoinKitTests/UInt256+BitcoinTests.swift +++ b/Tests/BitcoinKitTests/UInt256+BitcoinTests.swift @@ -37,28 +37,28 @@ class UInt256_BitcoinTests: XCTestCase { } func test1() { - XCTAssertEqual(try UInt256(compact: UInt32(0x007fffff)).hex, "0000000000000000000000000000000000000000000000000000000000000000") - XCTAssertEqual(try UInt256(compact: UInt32(0x017fffff)).hex, "000000000000000000000000000000000000000000000000000000000000007f") - XCTAssertEqual(try UInt256(compact: UInt32(0x027fffff)).hex, "0000000000000000000000000000000000000000000000000000000000007fff") - XCTAssertEqual(try UInt256(compact: UInt32(0x03123456)).hex, "0000000000000000000000000000000000000000000000000000000000123456") - XCTAssertEqual(try UInt256(compact: UInt32(0x037fffff)).hex, "00000000000000000000000000000000000000000000000000000000007fffff") - XCTAssertEqual(try UInt256(compact: UInt32(0x047fffff)).hex, "000000000000000000000000000000000000000000000000000000007fffff00") - XCTAssertEqual(try UInt256(compact: UInt32(0x057fffff)).hex, "0000000000000000000000000000000000000000000000000000007fffff0000") - XCTAssertEqual(try UInt256(compact: UInt32(0x067fffff)).hex, "00000000000000000000000000000000000000000000000000007fffff000000") - XCTAssertEqual(try UInt256(compact: UInt32(0x077fffff)).hex, "000000000000000000000000000000000000000000000000007fffff00000000") - XCTAssertEqual(try UInt256(compact: UInt32(0x087fffff)).hex, "0000000000000000000000000000000000000000000000007fffff0000000000") - XCTAssertEqual(try UInt256(compact: UInt32(0x097fffff)).hex, "00000000000000000000000000000000000000000000007fffff000000000000") - XCTAssertEqual(try UInt256(compact: UInt32(0x1d7fffff)).hex, "0000007fffff0000000000000000000000000000000000000000000000000000") - XCTAssertEqual(try UInt256(compact: UInt32(0x1e7fffff)).hex, "00007fffff000000000000000000000000000000000000000000000000000000") - XCTAssertEqual(try UInt256(compact: UInt32(0x1f7fffff)).hex, "007fffff00000000000000000000000000000000000000000000000000000000") - XCTAssertEqual(try UInt256(compact: UInt32(0x207fffff)).hex, "7fffff0000000000000000000000000000000000000000000000000000000000") - XCTAssertEqual(try UInt256(compact: UInt32(0x2100ffff)).hex, "ffff000000000000000000000000000000000000000000000000000000000000") - XCTAssertEqual(try UInt256(compact: UInt32(0x220000ff)).hex, "ff00000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual(try UInt256(compact: 0x007fffff as UInt32).hex, "0000000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual(try UInt256(compact: 0x017fffff as UInt32).hex, "000000000000000000000000000000000000000000000000000000000000007f") + XCTAssertEqual(try UInt256(compact: 0x027fffff as UInt32).hex, "0000000000000000000000000000000000000000000000000000000000007fff") + XCTAssertEqual(try UInt256(compact: 0x03123456 as UInt32).hex, "0000000000000000000000000000000000000000000000000000000000123456") + XCTAssertEqual(try UInt256(compact: 0x037fffff as UInt32).hex, "00000000000000000000000000000000000000000000000000000000007fffff") + XCTAssertEqual(try UInt256(compact: 0x047fffff as UInt32).hex, "000000000000000000000000000000000000000000000000000000007fffff00") + XCTAssertEqual(try UInt256(compact: 0x057fffff as UInt32).hex, "0000000000000000000000000000000000000000000000000000007fffff0000") + XCTAssertEqual(try UInt256(compact: 0x067fffff as UInt32).hex, "00000000000000000000000000000000000000000000000000007fffff000000") + XCTAssertEqual(try UInt256(compact: 0x077fffff as UInt32).hex, "000000000000000000000000000000000000000000000000007fffff00000000") + XCTAssertEqual(try UInt256(compact: 0x087fffff as UInt32).hex, "0000000000000000000000000000000000000000000000007fffff0000000000") + XCTAssertEqual(try UInt256(compact: 0x097fffff as UInt32).hex, "00000000000000000000000000000000000000000000007fffff000000000000") + XCTAssertEqual(try UInt256(compact: 0x1d7fffff as UInt32).hex, "0000007fffff0000000000000000000000000000000000000000000000000000") + XCTAssertEqual(try UInt256(compact: 0x1e7fffff as UInt32).hex, "00007fffff000000000000000000000000000000000000000000000000000000") + XCTAssertEqual(try UInt256(compact: 0x1f7fffff as UInt32).hex, "007fffff00000000000000000000000000000000000000000000000000000000") + XCTAssertEqual(try UInt256(compact: 0x207fffff as UInt32).hex, "7fffff0000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual(try UInt256(compact: 0x2100ffff as UInt32).hex, "ffff000000000000000000000000000000000000000000000000000000000000") + XCTAssertEqual(try UInt256(compact: 0x220000ff as UInt32).hex, "ff00000000000000000000000000000000000000000000000000000000000000") } func testOverflow() { do { - _ = try UInt256(compact: UInt32(0x21010000)) + _ = try UInt256(compact: 0x21010000 as UInt32) XCTFail() } catch UInt256.CompactError.overflow { } catch { @@ -66,7 +66,7 @@ class UInt256_BitcoinTests: XCTestCase { } do { - _ = try UInt256(compact: UInt32(0x22000100)) + _ = try UInt256(compact: 0x22000100 as UInt32) XCTFail() } catch UInt256.CompactError.overflow { } catch { @@ -74,7 +74,7 @@ class UInt256_BitcoinTests: XCTestCase { } do { - _ = try UInt256(compact: UInt32(0x23000001)) + _ = try UInt256(compact: 0x23000001 as UInt32) XCTFail() } catch UInt256.CompactError.overflow { } catch { @@ -82,7 +82,7 @@ class UInt256_BitcoinTests: XCTestCase { } do { - _ = try UInt256(compact: UInt32(0xff000001)) + _ = try UInt256(compact: 0xff000001 as UInt32) XCTFail() } catch UInt256.CompactError.overflow { } catch { @@ -93,7 +93,7 @@ class UInt256_BitcoinTests: XCTestCase { // negative func testNegative() { do { - _ = try UInt256(compact: UInt32(0x008fffff)) + _ = try UInt256(compact: 0x008fffff as UInt32) XCTFail() } catch UInt256.CompactError.negative { } catch { @@ -101,7 +101,7 @@ class UInt256_BitcoinTests: XCTestCase { } do { - _ = try UInt256(compact: UInt32(0x009fffff)) + _ = try UInt256(compact: 0x009fffff as UInt32) XCTFail() } catch UInt256.CompactError.negative { } catch { @@ -109,7 +109,7 @@ class UInt256_BitcoinTests: XCTestCase { } do { - _ = try UInt256(compact: UInt32(0x00ffffff)) + _ = try UInt256(compact: 0x00ffffff as UInt32) XCTFail() } catch UInt256.CompactError.negative { } catch { From a32a18a2101578acd313cf2e3e939d818556d352 Mon Sep 17 00:00:00 2001 From: Shun Usami Date: Thu, 12 Sep 2019 15:55:44 +0900 Subject: [PATCH 7/7] :recycle: Modify copyrights and add some test cases --- .../xcschemes/BitcoinKit.xcscheme | 1 + Sources/BitcoinKit/Core/Math.swift | 9 ++--- Sources/BitcoinKit/Core/MerkleTree.swift | 1 - Sources/BitcoinKit/Core/ProofOfWork.swift | 1 - Sources/BitcoinKit/Core/UInt256+Bitcoin.swift | 1 - Sources/BitcoinKit/Core/UInt256.swift | 21 ++++++++-- Sources/BitcoinKit/Core/UInt32+Utility.swift | 1 - Tests/BitcoinKitTests/ProofOfWorkTests.swift | 1 - .../UInt256+BitcoinTests.swift | 12 ++++-- Tests/BitcoinKitTests/UInt256Tests.swift | 40 ++++++++++++++++++- Tests/BitcoinKitTests/UInt32MathTests.swift | 1 - 11 files changed, 69 insertions(+), 20 deletions(-) diff --git a/BitcoinKit.xcodeproj/xcshareddata/xcschemes/BitcoinKit.xcscheme b/BitcoinKit.xcodeproj/xcshareddata/xcschemes/BitcoinKit.xcscheme index 4bb67004..1aa33740 100644 --- a/BitcoinKit.xcodeproj/xcshareddata/xcschemes/BitcoinKit.xcscheme +++ b/BitcoinKit.xcodeproj/xcshareddata/xcschemes/BitcoinKit.xcscheme @@ -26,6 +26,7 @@ buildConfiguration = "Debug" selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" + codeCoverageEnabled = "YES" shouldUseLaunchSchemeArgsEnv = "YES"> UInt32 { if x == 0 { return 0 } - var xx = x - var r: UInt32 = (xx & (xx - 1)) != 0 ? 1 : 0 - while true { + guard x > 1 else { return 0 } + var xx: UInt32 = x - 1 + var r: UInt32 = 0 + while xx > 0 { xx >>= 1 - if xx == 0 { break } r += 1 } return r diff --git a/Sources/BitcoinKit/Core/MerkleTree.swift b/Sources/BitcoinKit/Core/MerkleTree.swift index 42523ff7..58a0de72 100644 --- a/Sources/BitcoinKit/Core/MerkleTree.swift +++ b/Sources/BitcoinKit/Core/MerkleTree.swift @@ -1,7 +1,6 @@ // // MerkleTree.swift // -// Copyright © 2018 pebble8888 // Copyright © 2018 BitcoinKit developers // // Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/Sources/BitcoinKit/Core/ProofOfWork.swift b/Sources/BitcoinKit/Core/ProofOfWork.swift index cf91270f..6fc96952 100644 --- a/Sources/BitcoinKit/Core/ProofOfWork.swift +++ b/Sources/BitcoinKit/Core/ProofOfWork.swift @@ -1,7 +1,6 @@ // // ProofOfWork.swift // -// Copyright © 2018 pebble8888 // Copyright © 2018 BitcoinKit developers // // Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/Sources/BitcoinKit/Core/UInt256+Bitcoin.swift b/Sources/BitcoinKit/Core/UInt256+Bitcoin.swift index ef019f3b..a88e31d8 100644 --- a/Sources/BitcoinKit/Core/UInt256+Bitcoin.swift +++ b/Sources/BitcoinKit/Core/UInt256+Bitcoin.swift @@ -1,7 +1,6 @@ // // UInt256+Bitcoin.swift // -// Copyright © 2018 pebble8888 // Copyright © 2018 BitcoinKit developers // // Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/Sources/BitcoinKit/Core/UInt256.swift b/Sources/BitcoinKit/Core/UInt256.swift index 0cd00014..89a7a280 100644 --- a/Sources/BitcoinKit/Core/UInt256.swift +++ b/Sources/BitcoinKit/Core/UInt256.swift @@ -1,7 +1,6 @@ // // UInt256.swift // -// Copyright © 2018 pebble8888 // Copyright © 2018 BitcoinKit developers // // Permission is hereby granted, free of charge, to any person obtaining a copy @@ -112,7 +111,15 @@ extension UInt256: CustomDebugStringConvertible { extension UInt256: Equatable { public static func == (lhs: UInt256, rhs: UInt256) -> Bool { - if lhs.e0 != rhs.e0 { return false } else if lhs.e1 != rhs.e1 { return false } else if lhs.e2 != rhs.e2 { return false } else if lhs.e3 != rhs.e3 { return false } + if lhs.e0 != rhs.e0 { + return false + } else if lhs.e1 != rhs.e1 { + return false + } else if lhs.e2 != rhs.e2 { + return false + } else if lhs.e3 != rhs.e3 { + return false + } return true } } @@ -120,7 +127,15 @@ extension UInt256: Equatable { extension UInt256: Comparable { public static func < (lhs: UInt256, rhs: UInt256) -> Bool { // compare higest digit at first - if lhs.e3 != rhs.e3 { return lhs.e3 < rhs.e3 } else if lhs.e2 != rhs.e2 { return lhs.e2 < rhs.e2 } else if lhs.e1 != rhs.e1 { return lhs.e1 < rhs.e1 } else if lhs.e0 != rhs.e0 { return lhs.e0 < rhs.e0 } + if lhs.e3 != rhs.e3 { + return lhs.e3 < rhs.e3 + } else if lhs.e2 != rhs.e2 { + return lhs.e2 < rhs.e2 + } else if lhs.e1 != rhs.e1 { + return lhs.e1 < rhs.e1 + } else if lhs.e0 != rhs.e0 { + return lhs.e0 < rhs.e0 + } // a < a is always false (Irreflexivity) return false } diff --git a/Sources/BitcoinKit/Core/UInt32+Utility.swift b/Sources/BitcoinKit/Core/UInt32+Utility.swift index 05c36db8..ea7e6528 100644 --- a/Sources/BitcoinKit/Core/UInt32+Utility.swift +++ b/Sources/BitcoinKit/Core/UInt32+Utility.swift @@ -1,7 +1,6 @@ // // UInt32+Utility.swift // -// Copyright © 2018 pebble8888 // Copyright © 2018 BitcoinKit developers // // Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/Tests/BitcoinKitTests/ProofOfWorkTests.swift b/Tests/BitcoinKitTests/ProofOfWorkTests.swift index a8f2ae06..0d4cf6db 100644 --- a/Tests/BitcoinKitTests/ProofOfWorkTests.swift +++ b/Tests/BitcoinKitTests/ProofOfWorkTests.swift @@ -1,7 +1,6 @@ // // ProofOfWorkTests.swift // -// Copyright © 2018 pebble8888 // Copyright © 2018 BitcoinKit developers // // Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/Tests/BitcoinKitTests/UInt256+BitcoinTests.swift b/Tests/BitcoinKitTests/UInt256+BitcoinTests.swift index a938895b..a0cf66d5 100644 --- a/Tests/BitcoinKitTests/UInt256+BitcoinTests.swift +++ b/Tests/BitcoinKitTests/UInt256+BitcoinTests.swift @@ -1,7 +1,6 @@ // // UInt256+BitcoinTests.swift // -// Copyright © 2018 pebble8888 // Copyright © 2018 BitcoinKit developers // // Permission is hereby granted, free of charge, to any person obtaining a copy @@ -37,7 +36,12 @@ class UInt256_BitcoinTests: XCTestCase { } func test1() { + // size = 0 XCTAssertEqual(try UInt256(compact: 0x007fffff as UInt32).hex, "0000000000000000000000000000000000000000000000000000000000000000") + // target -0 + XCTAssertEqual(try UInt256(compact: 0x22800000 as UInt32).hex, "0000000000000000000000000000000000000000000000000000000000000000") + // target 0 + XCTAssertEqual(try UInt256(compact: 0x22000000 as UInt32).hex, "0000000000000000000000000000000000000000000000000000000000000000") XCTAssertEqual(try UInt256(compact: 0x017fffff as UInt32).hex, "000000000000000000000000000000000000000000000000000000000000007f") XCTAssertEqual(try UInt256(compact: 0x027fffff as UInt32).hex, "0000000000000000000000000000000000000000000000000000000000007fff") XCTAssertEqual(try UInt256(compact: 0x03123456 as UInt32).hex, "0000000000000000000000000000000000000000000000000000000000123456") @@ -93,7 +97,7 @@ class UInt256_BitcoinTests: XCTestCase { // negative func testNegative() { do { - _ = try UInt256(compact: 0x008fffff as UInt32) + _ = try UInt256(compact: 0x108fffff as UInt32) XCTFail() } catch UInt256.CompactError.negative { } catch { @@ -101,7 +105,7 @@ class UInt256_BitcoinTests: XCTestCase { } do { - _ = try UInt256(compact: 0x009fffff as UInt32) + _ = try UInt256(compact: 0x109fffff as UInt32) XCTFail() } catch UInt256.CompactError.negative { } catch { @@ -109,7 +113,7 @@ class UInt256_BitcoinTests: XCTestCase { } do { - _ = try UInt256(compact: 0x00ffffff as UInt32) + _ = try UInt256(compact: 0x10ffffff as UInt32) XCTFail() } catch UInt256.CompactError.negative { } catch { diff --git a/Tests/BitcoinKitTests/UInt256Tests.swift b/Tests/BitcoinKitTests/UInt256Tests.swift index f888fbdd..6e7a1e9e 100644 --- a/Tests/BitcoinKitTests/UInt256Tests.swift +++ b/Tests/BitcoinKitTests/UInt256Tests.swift @@ -1,7 +1,6 @@ // // UInt256Tests.swift // -// Copyright © 2018 pebble8888 // Copyright © 2018 BitcoinKit developers // // Permission is hereby granted, free of charge, to any person obtaining a copy @@ -213,6 +212,43 @@ class UInt256Tests: XCTestCase { XCTAssertTrue(UInt256(hex: "00000000_00000000_00000000_00000000_00000000_00000000_1200000f_0000000f")! < UInt256(hex: "00000000_00000000_00000000_00000000_00000000_00000000_1300000f_00000000")!) - } + + XCTAssertTrue(UInt256(hex: "00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000")! + < UInt256(hex: "10000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000")!) + + XCTAssertFalse(UInt256(hex: "00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000")! + < UInt256(hex: "00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000")!) +} + func testInitFromData() { + XCTAssertNotNil(UInt256(data: Data(count: 32))) + XCTAssertNil(UInt256(data: Data(count: 31))) + XCTAssertNil(UInt256(data: Data(count: 33))) + } + + func testInitFromUInt() { + XCTAssertEqual(UInt256(1 as UInt8).hex, "0000000000000000000000000000000000000000000000000000000000000001") + XCTAssertEqual(UInt256(1 as UInt16).hex, "0000000000000000000000000000000000000000000000000000000000000001") + XCTAssertEqual(UInt256(1 as UInt32).hex, "0000000000000000000000000000000000000000000000000000000000000001") + XCTAssertEqual(UInt256(1 as UInt64).hex, "0000000000000000000000000000000000000000000000000000000000000001") + XCTAssertEqual(UInt256(UInt8.max).hex, "00000000000000000000000000000000000000000000000000000000000000ff") + XCTAssertEqual(UInt256(UInt16.max).hex, "000000000000000000000000000000000000000000000000000000000000ffff") + XCTAssertEqual(UInt256(UInt32.max).hex, "00000000000000000000000000000000000000000000000000000000ffffffff") + XCTAssertEqual(UInt256(UInt64.max).hex, "000000000000000000000000000000000000000000000000ffffffffffffffff") + } + + func testEquatable() { + XCTAssertTrue(UInt256(hex: "00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000")! + == UInt256(hex: "00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000")!) + XCTAssertTrue(UInt256(hex: "11111111_00000000_00000000_00000000_00000000_00000000_00000000_00000000")! + == UInt256(hex: "11111111_00000000_00000000_00000000_00000000_00000000_00000000_00000000")!) + XCTAssertFalse(UInt256(hex: "00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000")! + == UInt256(hex: "10000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000")!) + XCTAssertFalse(UInt256(hex: "00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000")! + == UInt256(hex: "00000000_00000000_10000000_00000000_00000000_00000000_00000000_00000000")!) + XCTAssertFalse(UInt256(hex: "00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000")! + == UInt256(hex: "00000000_00000000_00000000_00000000_10000000_00000000_00000000_00000000")!) + XCTAssertFalse(UInt256(hex: "00000000_00000000_00000000_00000000_00000000_00000000_00000000_00000000")! + == UInt256(hex: "00000000_00000000_00000000_00000000_00000000_00000000_10000000_00000000")!) + } } diff --git a/Tests/BitcoinKitTests/UInt32MathTests.swift b/Tests/BitcoinKitTests/UInt32MathTests.swift index 50cfcfe9..df100750 100644 --- a/Tests/BitcoinKitTests/UInt32MathTests.swift +++ b/Tests/BitcoinKitTests/UInt32MathTests.swift @@ -1,7 +1,6 @@ // // UInt32MathTests.swift // -// Copyright © 2018 pebble8888 // Copyright © 2018 BitcoinKit developers // // Permission is hereby granted, free of charge, to any person obtaining a copy