From 0bc4ede65d27452ec3b6873b5c079052a0c04027 Mon Sep 17 00:00:00 2001 From: Shun Usami Date: Thu, 9 Aug 2018 08:03:23 +0900 Subject: [PATCH 1/2] :sparkles: Add and implement OpRipeMd160, OP_SHA1, OP_SHA256, OP_HASH256, OP_CODESEPARATOR except for OP_SHA1's implementation --- BitcoinCashKit.xcodeproj/project.pbxproj | 20 ++++++++++++++ .../Crypto Operators/OP_CODESEPARATOR.swift | 19 ++++++++++++++ .../OP_CODE/Crypto Operators/OP_HASH256.swift | 25 ++++++++++++++++++ .../Crypto Operators/OP_RIPEMD160.swift | 25 ++++++++++++++++++ .../OP_CODE/Crypto Operators/OP_SHA1.swift | 26 +++++++++++++++++++ .../OP_CODE/Crypto Operators/OP_SHA256.swift | 25 ++++++++++++++++++ BitcoinCashKit/Core/Scripts/Opcode.swift | 10 +++---- 7 files changed, 145 insertions(+), 5 deletions(-) create mode 100644 BitcoinCashKit/Core/Scripts/OP_CODE/Crypto Operators/OP_CODESEPARATOR.swift create mode 100644 BitcoinCashKit/Core/Scripts/OP_CODE/Crypto Operators/OP_HASH256.swift create mode 100644 BitcoinCashKit/Core/Scripts/OP_CODE/Crypto Operators/OP_RIPEMD160.swift create mode 100644 BitcoinCashKit/Core/Scripts/OP_CODE/Crypto Operators/OP_SHA1.swift create mode 100644 BitcoinCashKit/Core/Scripts/OP_CODE/Crypto Operators/OP_SHA256.swift diff --git a/BitcoinCashKit.xcodeproj/project.pbxproj b/BitcoinCashKit.xcodeproj/project.pbxproj index d0c1d7a2..94bb3d85 100644 --- a/BitcoinCashKit.xcodeproj/project.pbxproj +++ b/BitcoinCashKit.xcodeproj/project.pbxproj @@ -87,6 +87,11 @@ 14F37A3C20209F9200D34748 /* Script.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14F37A3B20209F9200D34748 /* Script.swift */; }; 14F37A3E2020A02000D34748 /* SighashType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14F37A3D2020A02000D34748 /* SighashType.swift */; }; 290880152109708000C79379 /* OpCodeProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 290880142109708000C79379 /* OpCodeProtocol.swift */; }; + 2914BE41211BAAC900B349CB /* OP_RIPEMD160.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2914BE40211BAAC900B349CB /* OP_RIPEMD160.swift */; }; + 2914BE43211BAAE500B349CB /* OP_SHA256.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2914BE42211BAAE500B349CB /* OP_SHA256.swift */; }; + 2914BE45211BAAF400B349CB /* OP_SHA1.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2914BE44211BAAF400B349CB /* OP_SHA1.swift */; }; + 2914BE47211BAB0500B349CB /* OP_HASH256.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2914BE46211BAB0500B349CB /* OP_HASH256.swift */; }; + 2914BE49211BAB1900B349CB /* OP_CODESEPARATOR.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2914BE48211BAB1900B349CB /* OP_CODESEPARATOR.swift */; }; 29248EEF2104B64E00CC9051 /* ScriptChunkHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29248EEE2104B64E00CC9051 /* ScriptChunkHelper.swift */; }; 29290B8D210AF59600D2BE78 /* OpCodeFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29290B8C210AF59600D2BE78 /* OpCodeFactory.swift */; }; 29290B91210AF79300D2BE78 /* OP_DUP.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29290B90210AF79300D2BE78 /* OP_DUP.swift */; }; @@ -247,6 +252,11 @@ 14F37A3B20209F9200D34748 /* Script.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Script.swift; sourceTree = ""; }; 14F37A3D2020A02000D34748 /* SighashType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SighashType.swift; sourceTree = ""; }; 290880142109708000C79379 /* OpCodeProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpCodeProtocol.swift; sourceTree = ""; }; + 2914BE40211BAAC900B349CB /* OP_RIPEMD160.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OP_RIPEMD160.swift; sourceTree = ""; }; + 2914BE42211BAAE500B349CB /* OP_SHA256.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OP_SHA256.swift; sourceTree = ""; }; + 2914BE44211BAAF400B349CB /* OP_SHA1.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OP_SHA1.swift; sourceTree = ""; }; + 2914BE46211BAB0500B349CB /* OP_HASH256.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OP_HASH256.swift; sourceTree = ""; }; + 2914BE48211BAB1900B349CB /* OP_CODESEPARATOR.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OP_CODESEPARATOR.swift; sourceTree = ""; }; 29248EEE2104B64E00CC9051 /* ScriptChunkHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScriptChunkHelper.swift; sourceTree = ""; }; 29290B8C210AF59600D2BE78 /* OpCodeFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpCodeFactory.swift; sourceTree = ""; }; 29290B90210AF79300D2BE78 /* OP_DUP.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OP_DUP.swift; sourceTree = ""; }; @@ -523,7 +533,12 @@ 294DDE38211B2B5900B7F645 /* Crypto Operators */ = { isa = PBXGroup; children = ( + 2914BE40211BAAC900B349CB /* OP_RIPEMD160.swift */, + 2914BE44211BAAF400B349CB /* OP_SHA1.swift */, + 2914BE42211BAAE500B349CB /* OP_SHA256.swift */, 29290B9A210AF88C00D2BE78 /* OP_HASH160.swift */, + 2914BE46211BAB0500B349CB /* OP_HASH256.swift */, + 2914BE48211BAB1900B349CB /* OP_CODESEPARATOR.swift */, 29290B96210AF87800D2BE78 /* OP_CHECKSIG.swift */, 29290BA6210C01E800D2BE78 /* OP_CHECKSIGVERIFY.swift */, 29E1ED72210ECD35007F4627 /* OP_CHECKMULTISIG.swift */, @@ -802,11 +817,13 @@ 294DDE3B211B31B100B7F645 /* OP_NOP.swift in Sources */, CFA2906E2101CDA3001A1BAB /* Opcode.swift in Sources */, 29290BA1210AF90D00D2BE78 /* OP_VERIFY.swift in Sources */, + 2914BE41211BAAC900B349CB /* OP_RIPEMD160.swift in Sources */, 29E1ED75210EF071007F4627 /* OP_CHECKMULTISIGVERIFY.swift in Sources */, 294DDE3F211B31CB00B7F645 /* OP_IF.swift in Sources */, 29290B8D210AF59600D2BE78 /* OpCodeFactory.swift in Sources */, 147F9729201FC89E0071F49D /* BloomFilter.swift in Sources */, 0C1DD40A211819CE004BA8A8 /* OP_GREATERTHAN.swift in Sources */, + 2914BE49211BAB1900B349CB /* OP_CODESEPARATOR.swift in Sources */, 29F5D1E6211068E8007DA3BF /* BigNumber.swift in Sources */, 0C1DD41021181AF3004BA8A8 /* OP_NUMEQUAL.swift in Sources */, 14839AA9202FE7DD00A6CB34 /* VarString.swift in Sources */, @@ -817,6 +834,7 @@ 29290B9B210AF88C00D2BE78 /* OP_HASH160.swift in Sources */, 14CDC3862021824200C01556 /* Wallet.swift in Sources */, 0C1DD41621181CC0004BA8A8 /* OP_GREATERTHANOREQUAL.swift in Sources */, + 2914BE45211BAAF400B349CB /* OP_SHA1.swift in Sources */, 29290B9D210AF8DF00D2BE78 /* OP_INVALIDOPCODE.swift in Sources */, 141FE2E42022589E00A08B04 /* PrivateKey.swift in Sources */, 299CB46F20EE1EA500B1245C /* Transaction+SignatureHash.swift in Sources */, @@ -824,6 +842,7 @@ 0C1DD40E21181AAC004BA8A8 /* OP_NUMNOTEQUAL.swift in Sources */, 0C1DD41D21182043004BA8A8 /* OP_SUB.swift in Sources */, 29290B93210AF86400D2BE78 /* OP_0.swift in Sources */, + 2914BE47211BAB0500B349CB /* OP_HASH256.swift in Sources */, 2949920020F227EB00D078B6 /* VersionByte.swift in Sources */, 29248EEF2104B64E00CC9051 /* ScriptChunkHelper.swift in Sources */, 14839A85202FE60E00A6CB34 /* InventoryMessage.swift in Sources */, @@ -864,6 +883,7 @@ 1482B5E22026B0680098B612 /* Mnemonic.swift in Sources */, 2949920620F22DCA00D078B6 /* UnsignedTransaction.swift in Sources */, 14839A9B202FE71200A6CB34 /* TransactionInput.swift in Sources */, + 2914BE43211BAAE500B349CB /* OP_SHA256.swift in Sources */, 0C0900342116A53F0077E9BC /* OP_NOT.swift in Sources */, CFA290722102B635001A1BAB /* ScriptMachine.swift in Sources */, 294DDE45211B31FA00B7F645 /* OP_VERNOTIF.swift in Sources */, diff --git a/BitcoinCashKit/Core/Scripts/OP_CODE/Crypto Operators/OP_CODESEPARATOR.swift b/BitcoinCashKit/Core/Scripts/OP_CODE/Crypto Operators/OP_CODESEPARATOR.swift new file mode 100644 index 00000000..30b4db7d --- /dev/null +++ b/BitcoinCashKit/Core/Scripts/OP_CODE/Crypto Operators/OP_CODESEPARATOR.swift @@ -0,0 +1,19 @@ +// +// OP_CODESEPARATOR.swift +// BitcoinCashKit +// +// Created by Shun Usami on 2018/08/09. +// Copyright © 2018 BitcoinCashKit developers. All rights reserved. +// + +import Foundation + +// All of the signature checking words will only match signatures to the data after the most recently-executed OP_CODESEPARATOR. +public struct OpCodeSeparator: OpCodeProtocol { + public var value: UInt8 { return 0xab } + public var name: String { return "OP_CODESEPARATOR" } + + public func mainProcess(_ context: ScriptExecutionContext) throws { + // do nothing + } +} diff --git a/BitcoinCashKit/Core/Scripts/OP_CODE/Crypto Operators/OP_HASH256.swift b/BitcoinCashKit/Core/Scripts/OP_CODE/Crypto Operators/OP_HASH256.swift new file mode 100644 index 00000000..97ff5317 --- /dev/null +++ b/BitcoinCashKit/Core/Scripts/OP_CODE/Crypto Operators/OP_HASH256.swift @@ -0,0 +1,25 @@ +// +// OP_HASH256.swift +// BitcoinCashKit +// +// Created by Shun Usami on 2018/08/09. +// Copyright © 2018 BitcoinCashKit developers. All rights reserved. +// + +import Foundation + +// The input is hashed two times with SHA-256. +public struct OpHash256: OpCodeProtocol { + public var value: UInt8 { return 0xaa } + public var name: String { return "OP_HASH256" } + + // input : in + // output : hash + public func mainProcess(_ context: ScriptExecutionContext) throws { + try context.assertStackHeightGreaterThan(1) + + let data: Data = context.stack.removeLast() + let hash: Data = Crypto.sha256sha256(data) + context.stack.append(hash) + } +} diff --git a/BitcoinCashKit/Core/Scripts/OP_CODE/Crypto Operators/OP_RIPEMD160.swift b/BitcoinCashKit/Core/Scripts/OP_CODE/Crypto Operators/OP_RIPEMD160.swift new file mode 100644 index 00000000..dc62aad5 --- /dev/null +++ b/BitcoinCashKit/Core/Scripts/OP_CODE/Crypto Operators/OP_RIPEMD160.swift @@ -0,0 +1,25 @@ +// +// OP_RIPEMD160.swift +// BitcoinCashKit +// +// Created by Shun Usami on 2018/08/09. +// Copyright © 2018 BitcoinCashKit developers. All rights reserved. +// + +import Foundation + +// The input is hashed using RIPEMD-160. +public struct OpRipemd160: OpCodeProtocol { + public var value: UInt8 { return 0xa6 } + public var name: String { return "OP_RIPEMD160" } + + // input : in + // output : hash + public func mainProcess(_ context: ScriptExecutionContext) throws { + try context.assertStackHeightGreaterThan(1) + + let data: Data = context.stack.removeLast() + let hash: Data = Crypto.ripemd160(data) + context.stack.append(hash) + } +} diff --git a/BitcoinCashKit/Core/Scripts/OP_CODE/Crypto Operators/OP_SHA1.swift b/BitcoinCashKit/Core/Scripts/OP_CODE/Crypto Operators/OP_SHA1.swift new file mode 100644 index 00000000..16b7389a --- /dev/null +++ b/BitcoinCashKit/Core/Scripts/OP_CODE/Crypto Operators/OP_SHA1.swift @@ -0,0 +1,26 @@ +// +// OP_SHA1.swift +// BitcoinCashKit +// +// Created by Shun Usami on 2018/08/09. +// Copyright © 2018 BitcoinCashKit developers. All rights reserved. +// + +import Foundation + +// The input is hashed using SHA-1. +public struct OpSha1: OpCodeProtocol { + public var value: UInt8 { return 0xa7 } + public var name: String { return "OP_SHA1" } + + // input : in + // output : hash + public func mainProcess(_ context: ScriptExecutionContext) throws { + try context.assertStackHeightGreaterThan(1) + + // TODO: Implement Crypto.sha1() + //let data: Data = context.stack.removeLast() + //let hash: Data = Crypto.sha1(data) + //context.stack.append(hash) + } +} diff --git a/BitcoinCashKit/Core/Scripts/OP_CODE/Crypto Operators/OP_SHA256.swift b/BitcoinCashKit/Core/Scripts/OP_CODE/Crypto Operators/OP_SHA256.swift new file mode 100644 index 00000000..c01d78d8 --- /dev/null +++ b/BitcoinCashKit/Core/Scripts/OP_CODE/Crypto Operators/OP_SHA256.swift @@ -0,0 +1,25 @@ +// +// OP_SHA256.swift +// BitcoinCashKit +// +// Created by Shun Usami on 2018/08/09. +// Copyright © 2018 BitcoinCashKit developers. All rights reserved. +// + +import Foundation + +// The input is hashed using SHA-256. +public struct OpSha256: OpCodeProtocol { + public var value: UInt8 { return 0xa8 } + public var name: String { return "OP_SHA256" } + + // input : in + // output : hash + public func mainProcess(_ context: ScriptExecutionContext) throws { + try context.assertStackHeightGreaterThan(1) + + let data: Data = context.stack.removeLast() + let hash: Data = Crypto.sha256(data) + context.stack.append(hash) + } +} diff --git a/BitcoinCashKit/Core/Scripts/Opcode.swift b/BitcoinCashKit/Core/Scripts/Opcode.swift index a9c45919..9fa54bd3 100644 --- a/BitcoinCashKit/Core/Scripts/Opcode.swift +++ b/BitcoinCashKit/Core/Scripts/Opcode.swift @@ -136,12 +136,12 @@ public enum OpCode: OpCodeProtocol { case .OP_WITHIN: return OpWithin() // Crypto - case .OP_RIPEMD160: return OpExample() - case .OP_SHA1: return OpExample() - case .OP_SHA256: return OpExample() + case .OP_RIPEMD160: return OpRipemd160() + case .OP_SHA1: return OpSha1() + case .OP_SHA256: return OpSha256() case .OP_HASH160: return OpHash160() - case .OP_HASH256: return OpExample() - case .OP_CODESEPARATOR: return OpExample() + case .OP_HASH256: return OpHash256() + case .OP_CODESEPARATOR: return OpCodeSeparator() case .OP_CHECKSIG: return OpCheckSig() case .OP_CHECKSIGVERIFY: return OpCheckSigVerify() case .OP_CHECKMULTISIG: return OpCheckMultiSig() From 665a21626961bb762a42cce0f02fa90699b57111 Mon Sep 17 00:00:00 2001 From: Shun Usami Date: Thu, 9 Aug 2018 08:08:31 +0900 Subject: [PATCH 2/2] :sparkles: Add SHA1 --- BitcoinCashKit/Core/BitcoinCashKitPrivate.h | 1 + BitcoinCashKit/Core/BitcoinCashKitPrivate.m | 6 ++++++ BitcoinCashKit/Core/Crypto.swift | 4 ++++ .../Core/Scripts/OP_CODE/Crypto Operators/OP_SHA1.swift | 7 +++---- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/BitcoinCashKit/Core/BitcoinCashKitPrivate.h b/BitcoinCashKit/Core/BitcoinCashKitPrivate.h index bfa0999c..65687934 100644 --- a/BitcoinCashKit/Core/BitcoinCashKitPrivate.h +++ b/BitcoinCashKit/Core/BitcoinCashKitPrivate.h @@ -29,6 +29,7 @@ NS_ASSUME_NONNULL_BEGIN @interface _Hash : NSObject ++ (NSData *)sha1:(NSData *)data; + (NSData *)sha256:(NSData *)data; + (NSData *)ripemd160:(NSData *)data; + (NSData *)hmacsha512:(NSData *)data key:(NSData *)key; diff --git a/BitcoinCashKit/Core/BitcoinCashKitPrivate.m b/BitcoinCashKit/Core/BitcoinCashKitPrivate.m index 3c82b3bb..6f6c2aa3 100644 --- a/BitcoinCashKit/Core/BitcoinCashKitPrivate.m +++ b/BitcoinCashKit/Core/BitcoinCashKitPrivate.m @@ -32,6 +32,12 @@ @implementation _Hash ++ (NSData *)sha1:(NSData *)data { + NSMutableData *result = [NSMutableData dataWithLength:SHA512_DIGEST_LENGTH]; + SHA1(data.bytes, data.length, result.mutableBytes); + return result; +} + + (NSData *)sha256:(NSData *)data { NSMutableData *result = [NSMutableData dataWithLength:SHA256_DIGEST_LENGTH]; SHA256(data.bytes, data.length, result.mutableBytes); diff --git a/BitcoinCashKit/Core/Crypto.swift b/BitcoinCashKit/Core/Crypto.swift index a6949534..df6d028f 100644 --- a/BitcoinCashKit/Core/Crypto.swift +++ b/BitcoinCashKit/Core/Crypto.swift @@ -28,6 +28,10 @@ import BitcoinCashKit.Private import secp256k1 public struct Crypto { + public static func sha1(_ data: Data) -> Data { + return _Hash.sha1(data) + } + public static func sha256(_ data: Data) -> Data { return _Hash.sha256(data) } diff --git a/BitcoinCashKit/Core/Scripts/OP_CODE/Crypto Operators/OP_SHA1.swift b/BitcoinCashKit/Core/Scripts/OP_CODE/Crypto Operators/OP_SHA1.swift index 16b7389a..01a34a90 100644 --- a/BitcoinCashKit/Core/Scripts/OP_CODE/Crypto Operators/OP_SHA1.swift +++ b/BitcoinCashKit/Core/Scripts/OP_CODE/Crypto Operators/OP_SHA1.swift @@ -18,9 +18,8 @@ public struct OpSha1: OpCodeProtocol { public func mainProcess(_ context: ScriptExecutionContext) throws { try context.assertStackHeightGreaterThan(1) - // TODO: Implement Crypto.sha1() - //let data: Data = context.stack.removeLast() - //let hash: Data = Crypto.sha1(data) - //context.stack.append(hash) + let data: Data = context.stack.removeLast() + let hash: Data = Crypto.sha1(data) + context.stack.append(hash) } }