diff --git a/.gitignore b/.gitignore index 32e51ca3..d304d727 100644 --- a/.gitignore +++ b/.gitignore @@ -108,3 +108,201 @@ my_id.txt #vscode local settings .vscode/ + + +# Created by https://www.gitignore.io/api/linux,swift,xcode,macos,carthage,cocoapods,objective-c +# Edit at https://www.gitignore.io/?templates=linux,swift,xcode,macos,carthage,cocoapods,objective-c + +### Carthage ### +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage + +### CocoaPods ### +## CocoaPods GitIgnore Template + +# CocoaPods - Only use to conserve bandwidth / Save time on Pushing +# - Also handy if you have a large number of dependant pods +# - AS PER https://guides.cocoapods.org/using/using-cocoapods.html NEVER IGNORE THE LOCK FILE +Pods/ + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Objective-C ### +# Xcode +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData/ + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata/ + +## Other +*.moved-aside +*.xccheckout +*.xcscmblueprint + +## Obj-C/Swift specific +*.hmap +*.ipa +*.dSYM.zip +*.dSYM + +# CocoaPods +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# Pods/ +# Add this line if you want to avoid checking in source code from the Xcode workspace +# *.xcworkspace + +# Carthage +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + + +# fastlane +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/#source-control + +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots/**/*.png +fastlane/test_output + +# Code Injection +# After new code Injection tools there's a generated folder /iOSInjectionProject +# https://github.com/johnno1962/injectionforxcode + +iOSInjectionProject/ + +### Objective-C Patch ### + +### Swift ### +# Xcode +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + + + + + +## Playgrounds +timeline.xctimeline +playground.xcworkspace + +# Swift Package Manager +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +# Package.pins +# Package.resolved +.build/ +# Add this line if you want to avoid checking in Xcode SPM integration. +# .swiftpm/xcode + +# CocoaPods +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# Pods/ +# Add this line if you want to avoid checking in source code from the Xcode workspace +# *.xcworkspace + +# Carthage +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + + +# Accio dependency management +Dependencies/ +.accio/ + +# fastlane +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/#source-control + + +# Code Injection +# After new code Injection tools there's a generated folder /iOSInjectionProject +# https://github.com/johnno1962/injectionforxcode + + +### Xcode ### +# Xcode +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) + +## Xcode Patch +*.xcodeproj/* +!*.xcodeproj/project.pbxproj +!*.xcodeproj/xcshareddata/ +!*.xcworkspace/contents.xcworkspacedata +/*.gcno + +### Xcode Patch ### +**/xcshareddata/WorkspaceSettings.xcsettings + +# End of https://www.gitignore.io/api/linux,swift,xcode,macos,carthage,cocoapods,objective-c + diff --git a/Pipfile.lock b/Pipfile.lock index da56139b..3839443f 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "36d1480b2857d3ca47d87e44b63f4bb1c3ba85e9fba71a9389c6f8161f5edd29" + "sha256": "1cfc261928838be069088d094d13b664d7ff98667a8a9b432e94c3241ab5ad6c" }, "pipfile-spec": 6, "requires": { @@ -18,10 +18,10 @@ "default": { "certifi": { "hashes": [ - "sha256:046832c04d4e752f37383b628bc601a7ea7211496b4638f6514d0e5b9acc4939", - "sha256:945e3ba63a0b9f577b1395204e13c3a231f9bc0223888be653286534e5873695" + "sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3", + "sha256:25b64c7da4cd7479594d035c08c2d809eb4aab3a26e5a990ea98cc450c320f1f" ], - "version": "==2019.6.16" + "version": "==2019.11.28" }, "chardet": { "hashes": [ @@ -39,18 +39,18 @@ }, "flask": { "hashes": [ - "sha256:0749df235e3ff61ac108f69ac178c9770caeaccad2509cb762ce1f65570a8856", - "sha256:49f44461237b69ecd901cc7ce66feea0319b9158743dd27a2899962ab214dac1" + "sha256:13f9f196f330c7c2c5d7a5cf91af894110ca0215ac051b5844701f2bfd934d52", + "sha256:45eb5a6fd193d6cf7e0cf5d8a5b31f83d5faae0293695626f539a823e93b13f6" ], "index": "pypi", - "version": "==0.12.2" + "version": "==1.1.1" }, "idna": { "hashes": [ - "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f", - "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4" + "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", + "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c" ], - "version": "==2.6" + "version": "==2.8" }, "itsdangerous": { "hashes": [ @@ -61,10 +61,10 @@ }, "jinja2": { "hashes": [ - "sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013", - "sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b" + "sha256:93187ffbc7808079673ef52771baa950426fd664d3aad1d0fa3e95644360e250", + "sha256:b0eaf100007721b5c16c1fc1eecb87409464edc10469ddc9a22a27a99123be49" ], - "version": "==2.10.1" + "version": "==2.11.1" }, "markupsafe": { "hashes": [ @@ -72,13 +72,16 @@ "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161", "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235", "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5", + "sha256:13d3144e1e340870b25e7b10b98d779608c02016d5184cfb9927a9f10c689f42", "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff", "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b", "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1", "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e", "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183", "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66", + "sha256:596510de112c685489095da617b5bcbbac7dd6384aeebeda4df6025d0256a81b", "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1", + "sha256:6788b695d50a51edb699cb55e35487e430fa21f1ed838122d722e0ff0ac5ba15", "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1", "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e", "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b", @@ -95,31 +98,33 @@ "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6", "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f", "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f", - "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7" + "sha256:cdb132fc825c38e1aeec2c8aa9338310d29d337bebbd7baa06889d09a60a1fa2", + "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7", + "sha256:e8313f01ba26fbbe36c7be1966a7b7424942f670f38e666995b88d012765b9be" ], "version": "==1.1.1" }, "requests": { "hashes": [ - "sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b", - "sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e" + "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4", + "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31" ], "index": "pypi", - "version": "==2.18.4" + "version": "==2.22.0" }, "urllib3": { "hashes": [ - "sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b", - "sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f" + "sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc", + "sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc" ], - "version": "==1.22" + "version": "==1.25.8" }, "werkzeug": { "hashes": [ - "sha256:865856ebb55c4dcd0630cdd8f3331a1847a819dda7e8c750d3db6f2aa6c0209c", - "sha256:a0b915f0815982fb2a09161cb8f31708052d0951c3ba433ccc5e1aa276507ca6" + "sha256:169ba8a33788476292d04186ab33b01d6add475033dfc07215e6d219cc077096", + "sha256:6dc65cf9091cf750012f56f2cad759fa9e879f511b5ff8685e456b4e3bf90d16" ], - "version": "==0.15.4" + "version": "==1.0.0" } }, "develop": { @@ -132,11 +137,11 @@ }, "flake8": { "hashes": [ - "sha256:859996073f341f2670741b51ec1e67a01da142831aa1fdc6242dbf88dffbe661", - "sha256:a796a115208f5c03b18f332f7c11729812c8c3ded6c46319c59b53efd3819da8" + "sha256:45681a117ecc81e870cbf1262835ae4af5e7a8b08e40b944a8a6e6b895914cfb", + "sha256:49356e766643ad15072a789a20915d3c91dc89fd313ccd71802303fd67e4deca" ], "index": "pypi", - "version": "==3.7.7" + "version": "==3.7.9" }, "mccabe": { "hashes": [ diff --git a/basic_block_gp/blockchain.py b/basic_block_gp/blockchain.py index 54ead5c1..dff13999 100644 --- a/basic_block_gp/blockchain.py +++ b/basic_block_gp/blockchain.py @@ -31,13 +31,20 @@ def new_block(self, proof, previous_hash=None): """ block = { - # TODO + 'index': len(self.chain) + 1, + 'timestamp': time(), + 'transactions': self.current_transactions, + 'proof': proof, + 'previous_hash': previous_hash or self.hash(self.chain[-1]) + } # Reset the current list of transactions - # Append the chain to the block + self.current_transactions = [] + # Append the block to the chain + self.chain.append(block) # Return the new block - pass + return block def hash(self, block): """ @@ -55,9 +62,11 @@ def hash(self, block): # We must make sure that the Dictionary is Ordered, # or we'll have inconsistent hashes - # TODO: Create the block_string + stringObject = json.dumps(block, sort_keys=True) + blockString = stringObject.encode() - # TODO: Hash this string using sha256 + rawHash = hashlib.sha256(blockString) + hexHash = rawHash.hexdigest() # By itself, the sha256 function returns the hash in a raw string # that will likely include escaped characters. @@ -66,7 +75,7 @@ def hash(self, block): # easier to work with and understand # TODO: Return the hashed block string in hexadecimal format - pass + return hexHash @property def last_block(self): @@ -80,9 +89,12 @@ def proof_of_work(self, block): in an effort to find a number that is a valid proof :return: A valid proof for the provided block """ - # TODO - pass - # return proof + blockString = json.dumps(block, sort_keys=True) + proof = 0 + while self.valid_proof(blockString, proof) is False: + proof += 1 + + return proof @staticmethod def valid_proof(block_string, proof): @@ -96,9 +108,10 @@ def valid_proof(block_string, proof): correct number of leading zeroes. :return: True if the resulting hash is a valid proof, False otherwise """ - # TODO - pass - # return True or False + guess = f"{block_string}{proof}".encode() + guessHash = hashlib.sha256(guess).hexdigest() + + return guessHash[:3] == "000" # Instantiate our Node @@ -114,11 +127,16 @@ def valid_proof(block_string, proof): @app.route('/mine', methods=['GET']) def mine(): # Run the proof of work algorithm to get the next proof + proof = blockchain.proof_of_work(blockchain.last_block) + + previousHash = blockchain.hash(blockchain.last_block) + newBlock = blockchain.new_block(proof, previousHash) # Forge the new Block by adding it to the chain with the proof response = { - # TODO: Send a JSON response with the new block + 'block': newBlock, + } return jsonify(response), 200 @@ -127,7 +145,9 @@ def mine(): @app.route('/chain', methods=['GET']) def full_chain(): response = { - # TODO: Return the chain and its current length + # Return the chain and its current length + 'chain': blockchain.chain, + 'length': len(blockchain.chain), } return jsonify(response), 200 diff --git a/basic_transactions_gp/blockchain.py b/basic_transactions_gp/blockchain.py index 5a2c7e5a..66ba5747 100644 --- a/basic_transactions_gp/blockchain.py +++ b/basic_transactions_gp/blockchain.py @@ -1,2 +1,213 @@ -# Paste your version of blockchain.py from the client_mining_p -# folder here +import hashlib +import json +from time import time +from uuid import uuid4 + +from flask import Flask, jsonify, request + + +class Blockchain(object): + def __init__(self): + self.chain = [] + self.current_transactions = [] + + # Create the genesis block + self.new_block(previous_hash="-1", proof=0) + + self.difficulty = 6 + + def new_block(self, proof, previous_hash=None): + """ + Create a new Block in the Blockchain + + A block should have: + * Index + * Timestamp + * List of current transactions + * The proof used to mine this block + * The hash of the previous block + + :param proof: The proof given by the Proof of Work algorithm + :param previous_hash: (Optional) Hash of previous Block + :return: New Block + """ + block = { + 'index': len(self.chain) + 1, + 'timestamp': time(), + 'transactions': self.current_transactions, + 'proof': proof, + 'previousHash': previous_hash or self.hash(self.chain[-1]) + } + + # Reset the current list of transactions + self.current_transactions = [] + # Append the block to the chain + self.chain.append(block) + # Return the new block + return block + + def newTransaction(self, sender, recipient, amount): + """ + : param sender: < str > Address of the Recipient + : param recipient: < str > Address of the Recipient + : param amount: < int > Amount + : return: < int > The index of the `block` that will hold this transaction + """ + transaction = { + "sender": sender, + "recipient": recipient, + "amount": float(amount), + "timestamp": time(), + "id": str(uuid4()) + } + + self.current_transactions.append(transaction) + + return self.last_block['index'] + 1 + + def hash(self, block): + """ + Creates a SHA-256 hash of a Block + + :param block": Block + "return": + """ + stringObject = json.dumps(block, sort_keys=True) + blockString = stringObject.encode() + + rawHash = hashlib.sha256(blockString) + hexHash = rawHash.hexdigest() + return hexHash + + def balanceForUser(self, user): + balance = 0 + allXtions = [block["transactions"] for block in self.chain] + allXtions += self.current_transactions + for blockTransactions in allXtions: + for transaction in blockTransactions: + if transaction["sender"] == user: + balance -= transaction["amount"] + if transaction["recipient"] == user: + balance += transaction["amount"] + + return balance + + @property + def last_block(self): + return self.chain[-1] + + @staticmethod + def valid_proof(block_string, proof): + """ + Validates the Proof: Does hash(block_string, proof) contain 3 + leading zeroes? Return true if the proof is valid + :param block_string: The stringified block to use to + check in combination with `proof` + :param proof: The value that when combined with the + stringified previous block results in a hash that has the + correct number of leading zeroes. + :return: True if the resulting hash is a valid proof, False otherwise + """ + guess = f"{block_string}{proof}".encode() + guessHash = hashlib.sha256(guess).hexdigest() + + return guessHash[:blockchain.difficulty] == "0" * blockchain.difficulty + + @staticmethod + def valid_proof_block(block, proof): + properties = [block.get("index", None), block.get("timestamp", None), block.get( + "transactions", None), block.get("proof", None), block.get("previousHash", None)] + if len([x for x in properties if x is not None]) != 5: + print("invalid block structure") + return False + blockString = json.dumps(block, sort_keys=True) + return Blockchain.valid_proof(blockString, proof) + + +# Instantiate our Node +app = Flask(__name__) + +# Generate a globally unique address for this node +node_identifier = str(uuid4()).replace('-', '') + +# Instantiate the Blockchain +blockchain = Blockchain() + + +@app.route('/mine', methods=['POST']) +def mine(): + jsonStr = request.data.decode("utf-8") + incomingMinedBlock = json.loads(jsonStr) + newProof = incomingMinedBlock.get("proof", None) + clientID = incomingMinedBlock.get("id", None) + if newProof is None or clientID is None: + return jsonify({"error": "Invalid proof info"}), 400 + newProof = int(newProof) + + if Blockchain.valid_proof_block(blockchain.last_block, newProof): + # successful = add new block and return message indicating success + previousHash = blockchain.hash(blockchain.last_block) + + blockIndex = blockchain.newTransaction("0", clientID, 1) + + newBlock = blockchain.new_block(newProof, previousHash) + response = { + "status": "success", + "block": newBlock, + "reward": f"reward paid in block {blockIndex}" + } + return jsonify(response), 200 + else: + response = { + "status": "failure", + } + return jsonify(response), 200 + + +@app.route('/chain', methods=['GET']) +def full_chain(): + response = { + # Return the chain and its current length + 'chain': blockchain.chain, + 'length': len(blockchain.chain), + } + return jsonify(response), 200 + +@app.route("/transaction/new", methods=['POST']) +def receiveNewTransaction(): + jsonStr = request.data.decode("utf-8") + data = json.loads(jsonStr) + # data = request.get_json() + + required = ['sender', 'recipient', 'amount'] + if not all(k in data for k in required): + return jsonify({"error": "Missing Values"}), 400 + sender = data['sender'] + recipient = data['recipient'] + amount = float(data['amount']) + + if blockchain.balanceForUser(sender) < amount: + response = { + "message": f"Insuffienct balance" + } + return jsonify(response), 200 + + index = blockchain.newTransaction(sender, recipient, amount) + response = { + "message": f"Transactions will be included in block {index}" + } + return jsonify(response), 200 + +@app.route('/lastblock', methods=['GET']) +def lastBlock(): + return jsonify(blockchain.last_block), 200 + + +@app.route("/difficulty", methods=["GET"]) +def difficulty(): + return jsonify(blockchain.difficulty), 200 + + +# Run the program on port 5000 +if __name__ == '__main__': + app.run(host='0.0.0.0', port=5000) diff --git a/basic_wallet_p/BCWallet/BCWallet.xcodeproj/project.pbxproj b/basic_wallet_p/BCWallet/BCWallet.xcodeproj/project.pbxproj new file mode 100644 index 00000000..88741ee1 --- /dev/null +++ b/basic_wallet_p/BCWallet/BCWallet.xcodeproj/project.pbxproj @@ -0,0 +1,407 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 51; + objects = { + +/* Begin PBXBuildFile section */ + 33C45B5623F5F12A00D73231 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33C45B5523F5F12A00D73231 /* AppDelegate.swift */; }; + 33C45B5823F5F12A00D73231 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33C45B5723F5F12A00D73231 /* SceneDelegate.swift */; }; + 33C45B5A23F5F12A00D73231 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33C45B5923F5F12A00D73231 /* ContentView.swift */; }; + 33C45B5C23F5F12E00D73231 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33C45B5B23F5F12E00D73231 /* Assets.xcassets */; }; + 33C45B5F23F5F12E00D73231 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33C45B5E23F5F12E00D73231 /* Preview Assets.xcassets */; }; + 33C45B6223F5F12E00D73231 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 33C45B6023F5F12E00D73231 /* LaunchScreen.storyboard */; }; + 33C45B6A23F602A700D73231 /* Cartfile in Resources */ = {isa = PBXBuildFile; fileRef = 33C45B6923F602A700D73231 /* Cartfile */; }; + 33C45B6D23F6031100D73231 /* input.xcfilelist in Resources */ = {isa = PBXBuildFile; fileRef = 33C45B6B23F6031100D73231 /* input.xcfilelist */; }; + 33C45B6E23F6031100D73231 /* output.xcfilelist in Resources */ = {isa = PBXBuildFile; fileRef = 33C45B6C23F6031100D73231 /* output.xcfilelist */; }; + 33C45B7123F6032F00D73231 /* NetworkHandler.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 33C45B7023F6032F00D73231 /* NetworkHandler.framework */; }; + 33C45B7423F603B900D73231 /* ChainController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33C45B7323F603B900D73231 /* ChainController.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 33C45B5223F5F12A00D73231 /* BCWallet.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BCWallet.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 33C45B5523F5F12A00D73231 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33C45B5723F5F12A00D73231 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + 33C45B5923F5F12A00D73231 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + 33C45B5B23F5F12E00D73231 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 33C45B5E23F5F12E00D73231 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 33C45B6123F5F12E00D73231 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 33C45B6323F5F12E00D73231 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 33C45B6923F602A700D73231 /* Cartfile */ = {isa = PBXFileReference; lastKnownFileType = text; path = Cartfile; sourceTree = ""; }; + 33C45B6B23F6031100D73231 /* input.xcfilelist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcfilelist; path = input.xcfilelist; sourceTree = ""; }; + 33C45B6C23F6031100D73231 /* output.xcfilelist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcfilelist; path = output.xcfilelist; sourceTree = ""; }; + 33C45B7023F6032F00D73231 /* NetworkHandler.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NetworkHandler.framework; path = Carthage/Build/iOS/NetworkHandler.framework; sourceTree = ""; }; + 33C45B7323F603B900D73231 /* ChainController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChainController.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 33C45B4F23F5F12A00D73231 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 33C45B7123F6032F00D73231 /* NetworkHandler.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 33C45B4923F5F12A00D73231 = { + isa = PBXGroup; + children = ( + 33C45B6923F602A700D73231 /* Cartfile */, + 33C45B6B23F6031100D73231 /* input.xcfilelist */, + 33C45B6C23F6031100D73231 /* output.xcfilelist */, + 33C45B5423F5F12A00D73231 /* BCWallet */, + 33C45B5323F5F12A00D73231 /* Products */, + 33C45B6F23F6032300D73231 /* Frameworks */, + ); + sourceTree = ""; + }; + 33C45B5323F5F12A00D73231 /* Products */ = { + isa = PBXGroup; + children = ( + 33C45B5223F5F12A00D73231 /* BCWallet.app */, + ); + name = Products; + sourceTree = ""; + }; + 33C45B5423F5F12A00D73231 /* BCWallet */ = { + isa = PBXGroup; + children = ( + 33C45B5523F5F12A00D73231 /* AppDelegate.swift */, + 33C45B5723F5F12A00D73231 /* SceneDelegate.swift */, + 33C45B5923F5F12A00D73231 /* ContentView.swift */, + 33C45B7323F603B900D73231 /* ChainController.swift */, + 33C45B5B23F5F12E00D73231 /* Assets.xcassets */, + 33C45B6023F5F12E00D73231 /* LaunchScreen.storyboard */, + 33C45B6323F5F12E00D73231 /* Info.plist */, + 33C45B5D23F5F12E00D73231 /* Preview Content */, + ); + path = BCWallet; + sourceTree = ""; + }; + 33C45B5D23F5F12E00D73231 /* Preview Content */ = { + isa = PBXGroup; + children = ( + 33C45B5E23F5F12E00D73231 /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; + 33C45B6F23F6032300D73231 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 33C45B7023F6032F00D73231 /* NetworkHandler.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 33C45B5123F5F12A00D73231 /* BCWallet */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33C45B6623F5F12E00D73231 /* Build configuration list for PBXNativeTarget "BCWallet" */; + buildPhases = ( + 33C45B4E23F5F12A00D73231 /* Sources */, + 33C45B4F23F5F12A00D73231 /* Frameworks */, + 33C45B5023F5F12A00D73231 /* Resources */, + 33C45B7223F6033C00D73231 /* Run Script - Carthage */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = BCWallet; + productName = BCWallet; + productReference = 33C45B5223F5F12A00D73231 /* BCWallet.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33C45B4A23F5F12A00D73231 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 1130; + LastUpgradeCheck = 1130; + ORGANIZATIONNAME = "Red_Egg Productions"; + TargetAttributes = { + 33C45B5123F5F12A00D73231 = { + CreatedOnToolsVersion = 11.3.1; + }; + }; + }; + buildConfigurationList = 33C45B4D23F5F12A00D73231 /* Build configuration list for PBXProject "BCWallet" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33C45B4923F5F12A00D73231; + productRefGroup = 33C45B5323F5F12A00D73231 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33C45B5123F5F12A00D73231 /* BCWallet */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 33C45B5023F5F12A00D73231 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33C45B6223F5F12E00D73231 /* LaunchScreen.storyboard in Resources */, + 33C45B6D23F6031100D73231 /* input.xcfilelist in Resources */, + 33C45B5F23F5F12E00D73231 /* Preview Assets.xcassets in Resources */, + 33C45B6E23F6031100D73231 /* output.xcfilelist in Resources */, + 33C45B6A23F602A700D73231 /* Cartfile in Resources */, + 33C45B5C23F5F12E00D73231 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 33C45B7223F6033C00D73231 /* Run Script - Carthage */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "$(SRCROOT)/input.xcfilelist", + ); + inputPaths = ( + ); + name = "Run Script - Carthage"; + outputFileListPaths = ( + "$(SRCROOT)/output.xcfilelist", + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/usr/local/bin/carthage copy-frameworks\n/usr/local/bin/carthage outdated --xcode-warnings\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 33C45B4E23F5F12A00D73231 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33C45B5623F5F12A00D73231 /* AppDelegate.swift in Sources */, + 33C45B5823F5F12A00D73231 /* SceneDelegate.swift in Sources */, + 33C45B5A23F5F12A00D73231 /* ContentView.swift in Sources */, + 33C45B7423F603B900D73231 /* ChainController.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 33C45B6023F5F12E00D73231 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 33C45B6123F5F12E00D73231 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 33C45B6423F5F12E00D73231 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33C45B6523F5F12E00D73231 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.2; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 33C45B6723F5F12E00D73231 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_ASSET_PATHS = "\"BCWallet/Preview Content\""; + DEVELOPMENT_TEAM = VXUQXR6S56; + ENABLE_PREVIEWS = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + INFOPLIST_FILE = BCWallet/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.redeggproductions.BCWallet; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 33C45B6823F5F12E00D73231 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_ASSET_PATHS = "\"BCWallet/Preview Content\""; + DEVELOPMENT_TEAM = VXUQXR6S56; + ENABLE_PREVIEWS = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/Carthage/Build/iOS", + ); + INFOPLIST_FILE = BCWallet/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.redeggproductions.BCWallet; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 33C45B4D23F5F12A00D73231 /* Build configuration list for PBXProject "BCWallet" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33C45B6423F5F12E00D73231 /* Debug */, + 33C45B6523F5F12E00D73231 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33C45B6623F5F12E00D73231 /* Build configuration list for PBXNativeTarget "BCWallet" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33C45B6723F5F12E00D73231 /* Debug */, + 33C45B6823F5F12E00D73231 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33C45B4A23F5F12A00D73231 /* Project object */; +} diff --git a/basic_wallet_p/BCWallet/BCWallet.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/basic_wallet_p/BCWallet/BCWallet.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 00000000..0ad83744 --- /dev/null +++ b/basic_wallet_p/BCWallet/BCWallet.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/basic_wallet_p/BCWallet/BCWallet.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/basic_wallet_p/BCWallet/BCWallet.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 00000000..18d98100 --- /dev/null +++ b/basic_wallet_p/BCWallet/BCWallet.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/basic_wallet_p/BCWallet/BCWallet/AppDelegate.swift b/basic_wallet_p/BCWallet/BCWallet/AppDelegate.swift new file mode 100644 index 00000000..f318a2b2 --- /dev/null +++ b/basic_wallet_p/BCWallet/BCWallet/AppDelegate.swift @@ -0,0 +1,37 @@ +// +// AppDelegate.swift +// BCWallet +// +// Created by Michael Redig on 2/13/20. +// Copyright © 2020 Red_Egg Productions. All rights reserved. +// + +import UIKit + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate { + + + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Override point for customization after application launch. + return true + } + + // MARK: UISceneSession Lifecycle + + func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { + // Called when a new scene session is being created. + // Use this method to select a configuration to create the new scene with. + return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) + } + + func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { + // Called when the user discards a scene session. + // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. + // Use this method to release any resources that were specific to the discarded scenes, as they will not return. + } + + +} + diff --git a/basic_wallet_p/BCWallet/BCWallet/Assets.xcassets/AppIcon.appiconset/Contents.json b/basic_wallet_p/BCWallet/BCWallet/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..d8db8d65 --- /dev/null +++ b/basic_wallet_p/BCWallet/BCWallet/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/basic_wallet_p/BCWallet/BCWallet/Assets.xcassets/Contents.json b/basic_wallet_p/BCWallet/BCWallet/Assets.xcassets/Contents.json new file mode 100644 index 00000000..da4a164c --- /dev/null +++ b/basic_wallet_p/BCWallet/BCWallet/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/basic_wallet_p/BCWallet/BCWallet/Base.lproj/LaunchScreen.storyboard b/basic_wallet_p/BCWallet/BCWallet/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 00000000..865e9329 --- /dev/null +++ b/basic_wallet_p/BCWallet/BCWallet/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/basic_wallet_p/BCWallet/BCWallet/ChainController.swift b/basic_wallet_p/BCWallet/BCWallet/ChainController.swift new file mode 100644 index 00000000..e92ca7e3 --- /dev/null +++ b/basic_wallet_p/BCWallet/BCWallet/ChainController.swift @@ -0,0 +1,116 @@ +// +// ChainController.swift +// BCWallet +// +// Created by Michael Redig on 2/13/20. +// Copyright © 2020 Red_Egg Productions. All rights reserved. +// + +import Foundation +import NetworkHandler + +class ChainController { + + var chain: [Block] = [] + let handler = NetworkHandler() + + private let baseURL = URL(string: "http://localhost:5000")! + + func getLatestChain(completion: @escaping (ChainController) -> Void) { + let url = baseURL.appendingPathComponent("chain") + + handler.transferMahCodableDatas(with: url.request) { (result: Result) -> Void in + switch result { + case .success(let chain): + self.chain = chain.chain + case .failure(let error): + print("error fetching chain: \(error)") + } + completion(self) + } + } + + func sendMoney(from sender: String, to recipient: String, amount: Double, completion: @escaping (ChainController, NetworkError?) -> Void) { + let url = baseURL + .appendingPathComponent("transaction") + .appendingPathComponent("new") + + let trans = Transaction(sender: sender, recipient: recipient, amount: amount, timestamp: Date().timeIntervalSince1970, id: "") + + let json = try! JSONEncoder().encode(trans) + + var request = url.request + request.httpMethod = .post + request.httpBody = json + request.addValue(.contentType(type: .json), forHTTPHeaderField: .commonKey(key: .contentType)) + + handler.transferMahCodableDatas(with: request) { (result: Result) -> Void in + switch result { + case .success: + completion(self, nil) + case .failure(let error): + completion(self, error) + switch error { + case .httpNon200StatusCode(code: let code, data: let data): + print(code) + let str = String(data: data!, encoding: .utf8)! + print(str) + default: + break + } + } + } + } + + func transactions(for user: String) -> [Transaction] { + chain.flatMap { $0.transactions }.filter { $0.sender == user || $0.recipient == user } + } + + func balance(for user: String, transactions: [Transaction]) -> (balance: Double, sent: Double, received: Double) { + var balance = 0.0 + var totalSent = 0.0 + var totalReceived = 0.0 + + for transaction in transactions { + if transaction.sender == user { + balance -= transaction.amount + totalSent += transaction.amount + } + if transaction.recipient == user { + balance += transaction.amount + totalReceived += transaction.amount + } + } + + return (balance, totalSent, totalReceived) + } +} + +struct Chain: Codable { + let chain: [Block] + let length: Int +} + +struct Block: Codable { + let index: Int + let previousHash: String + let proof: Int + let timestamp: Double + let transactions: [Transaction] +} + +struct Transaction: Codable, Hashable, CustomStringConvertible { + let sender: String + let recipient: String + let amount: Double + let timestamp: Double + let id: String + + var description: String { + "\(sender) sent \(amount) coins to \(recipient) at \(timestamp)" + } +} + +struct Message: Codable { + let message: String +} diff --git a/basic_wallet_p/BCWallet/BCWallet/ContentView.swift b/basic_wallet_p/BCWallet/BCWallet/ContentView.swift new file mode 100644 index 00000000..ec0b4e7c --- /dev/null +++ b/basic_wallet_p/BCWallet/BCWallet/ContentView.swift @@ -0,0 +1,110 @@ +// +// ContentView.swift +// BCWallet +// +// Created by Michael Redig on 2/13/20. +// Copyright © 2020 Red_Egg Productions. All rights reserved. +// + +import SwiftUI +import NetworkHandler + +struct ContentView: View { + + private let controller = ChainController() + + @State private var data = [Transaction]() + + @State private var userID = "" + @State private var totalSent = 0.0 + @State private var totalReceived = 0.0 + @State private var currentBalance = 0.0 + + @State private var sendAmount = "" + @State private var recipient = "" + + var body: some View { + Form { + Section(header: Text("Sign In:")) { + HStack(alignment: .center) { + Text("Enter your ID: ") + TextField("mahname", text: $userID) + .textFieldStyle(RoundedBorderTextFieldStyle()) + .textContentType(.username) + .autocapitalization(.none) + Button(action: fetchBalance) { + Text("Submit") + } + } + .frame(maxWidth: .infinity) + } + + Section(header: Text("Send Money")) { + HStack { + TextField("0", text: $sendAmount) + .textFieldStyle(RoundedBorderTextFieldStyle()) + .keyboardType(.decimalPad) + .textContentType(.oneTimeCode) + .autocapitalization(.none) + Text("to") + TextField("recipient", text: $recipient) + .textFieldStyle(RoundedBorderTextFieldStyle()) + .textContentType(.username) + .autocapitalization(.none) + Button(action: sendMoney) { + Text("Send") + } + } + } + + Section(header: Text("Current Balance")) { + Text("\(currentBalance) coins") + } + Section(header: Text("Total Sent")) { + Text("\(totalSent) coins") + } + Section(header: Text("Total Received")) { + Text("\(totalReceived) coins") + } + + Section(header: Text("Data")) { + List(data, id: \.self) { datum in + Text("\(datum.description)") + } + } + } + } + + func fetchBalance() { + controller.getLatestChain { controller in + let transactions = controller.transactions(for: self.userID) + self.data = transactions + + let balanceInfo = controller.balance(for: self.userID, transactions: transactions) + self.currentBalance = balanceInfo.balance + self.totalSent = balanceInfo.sent + self.totalReceived = balanceInfo.received + } + } + + func sendMoney() { + guard let amount = Double(sendAmount) else { return } + + controller.sendMoney(from: userID, to: recipient, amount: amount) { controller, error in + if let error = error { + print("error: \(error)") + return + } + self.fetchBalance() + } + + sendAmount = "" + recipient = "" + } +} + +struct ContentView_Previews: PreviewProvider { + static var previews: some View { + ContentView() + } +} diff --git a/basic_wallet_p/BCWallet/BCWallet/Info.plist b/basic_wallet_p/BCWallet/BCWallet/Info.plist new file mode 100644 index 00000000..cf16f92d --- /dev/null +++ b/basic_wallet_p/BCWallet/BCWallet/Info.plist @@ -0,0 +1,65 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSRequiresIPhoneOS + + NSAppTransportSecurity + + NSAllowsArbitraryLoads + + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneConfigurationName + Default Configuration + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + + + + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/basic_wallet_p/BCWallet/BCWallet/Preview Content/Preview Assets.xcassets/Contents.json b/basic_wallet_p/BCWallet/BCWallet/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 00000000..da4a164c --- /dev/null +++ b/basic_wallet_p/BCWallet/BCWallet/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/basic_wallet_p/BCWallet/BCWallet/SceneDelegate.swift b/basic_wallet_p/BCWallet/BCWallet/SceneDelegate.swift new file mode 100644 index 00000000..e35d5e89 --- /dev/null +++ b/basic_wallet_p/BCWallet/BCWallet/SceneDelegate.swift @@ -0,0 +1,64 @@ +// +// SceneDelegate.swift +// BCWallet +// +// Created by Michael Redig on 2/13/20. +// Copyright © 2020 Red_Egg Productions. All rights reserved. +// + +import UIKit +import SwiftUI + +class SceneDelegate: UIResponder, UIWindowSceneDelegate { + + var window: UIWindow? + + + func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { + // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. + // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. + // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). + + // Create the SwiftUI view that provides the window contents. + let contentView = ContentView() + + // Use a UIHostingController as window root view controller. + if let windowScene = scene as? UIWindowScene { + let window = UIWindow(windowScene: windowScene) + window.rootViewController = UIHostingController(rootView: contentView) + self.window = window + window.makeKeyAndVisible() + } + } + + func sceneDidDisconnect(_ scene: UIScene) { + // Called as the scene is being released by the system. + // This occurs shortly after the scene enters the background, or when its session is discarded. + // Release any resources associated with this scene that can be re-created the next time the scene connects. + // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). + } + + func sceneDidBecomeActive(_ scene: UIScene) { + // Called when the scene has moved from an inactive state to an active state. + // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. + } + + func sceneWillResignActive(_ scene: UIScene) { + // Called when the scene will move from an active state to an inactive state. + // This may occur due to temporary interruptions (ex. an incoming phone call). + } + + func sceneWillEnterForeground(_ scene: UIScene) { + // Called as the scene transitions from the background to the foreground. + // Use this method to undo the changes made on entering the background. + } + + func sceneDidEnterBackground(_ scene: UIScene) { + // Called as the scene transitions from the foreground to the background. + // Use this method to save data, release shared resources, and store enough scene-specific state information + // to restore the scene back to its current state. + } + + +} + diff --git a/basic_wallet_p/BCWallet/Cartfile b/basic_wallet_p/BCWallet/Cartfile new file mode 100644 index 00000000..cd2654c1 --- /dev/null +++ b/basic_wallet_p/BCWallet/Cartfile @@ -0,0 +1 @@ +github "mredig/NetworkHandler" diff --git a/basic_wallet_p/BCWallet/Cartfile.resolved b/basic_wallet_p/BCWallet/Cartfile.resolved new file mode 100644 index 00000000..54b7f928 --- /dev/null +++ b/basic_wallet_p/BCWallet/Cartfile.resolved @@ -0,0 +1 @@ +github "mredig/NetworkHandler" "0.9.4" diff --git a/basic_wallet_p/BCWallet/input.xcfilelist b/basic_wallet_p/BCWallet/input.xcfilelist new file mode 100644 index 00000000..251bcc6b --- /dev/null +++ b/basic_wallet_p/BCWallet/input.xcfilelist @@ -0,0 +1 @@ +$(SRCROOT)/Carthage/Build/iOS/NetworkHandler.framework diff --git a/basic_wallet_p/BCWallet/output.xcfilelist b/basic_wallet_p/BCWallet/output.xcfilelist new file mode 100644 index 00000000..67744566 --- /dev/null +++ b/basic_wallet_p/BCWallet/output.xcfilelist @@ -0,0 +1 @@ +$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/NetworkHandler.framework diff --git a/client_mining_p/blockchain.py b/client_mining_p/blockchain.py index a0a26551..68892766 100644 --- a/client_mining_p/blockchain.py +++ b/client_mining_p/blockchain.py @@ -1,2 +1,163 @@ -# Paste your version of blockchain.py from the basic_block_gp -# folder here +import hashlib +import json +from time import time +from uuid import uuid4 + +from flask import Flask, jsonify, request + + +class Blockchain(object): + def __init__(self): + self.chain = [] + self.current_transactions = [] + + # Create the genesis block + self.new_block(previous_hash=-1, proof=0) + + self.difficulty = 5 + + def new_block(self, proof, previous_hash=None): + """ + Create a new Block in the Blockchain + + A block should have: + * Index + * Timestamp + * List of current transactions + * The proof used to mine this block + * The hash of the previous block + + :param proof: The proof given by the Proof of Work algorithm + :param previous_hash: (Optional) Hash of previous Block + :return: New Block + """ + block = { + 'index': len(self.chain) + 1, + 'timestamp': time(), + 'transactions': self.current_transactions, + 'proof': proof, + 'previous_hash': previous_hash or self.hash(self.chain[-1]) + } + + # Reset the current list of transactions + self.current_transactions = [] + # Append the block to the chain + self.chain.append(block) + # Return the new block + return block + + def hash(self, block): + """ + Creates a SHA-256 hash of a Block + + :param block": Block + "return": + """ + stringObject = json.dumps(block, sort_keys=True) + blockString = stringObject.encode() + + rawHash = hashlib.sha256(blockString) + hexHash = rawHash.hexdigest() + return hexHash + + @property + def last_block(self): + return self.chain[-1] + + # def proof_of_work(self, block): + # """ + # Simple Proof of Work Algorithm + # Stringify the block and look for a proof. + # Loop through possibilities, checking each one against `valid_proof` + # in an effort to find a number that is a valid proof + # :return: A valid proof for the provided block + # """ + # blockString = json.dumps(block, sort_keys=True) + # proof = 0 + # while self.valid_proof(blockString, proof) is False: + # proof += 1 + + # return proof + + @staticmethod + def valid_proof(block_string, proof): + """ + Validates the Proof: Does hash(block_string, proof) contain 3 + leading zeroes? Return true if the proof is valid + :param block_string: The stringified block to use to + check in combination with `proof` + :param proof: The value that when combined with the + stringified previous block results in a hash that has the + correct number of leading zeroes. + :return: True if the resulting hash is a valid proof, False otherwise + """ + guess = f"{block_string}{proof}".encode() + guessHash = hashlib.sha256(guess).hexdigest() + + return guessHash[:blockchain.difficulty] == "0" * blockchain.difficulty + + @staticmethod + def valid_proof_block(block, proof): + properties = [block.get("index", None), block.get("timestamp", None), block.get("transactions", None), block.get("proof", None), block.get("previous_hash", None)] + if len([x for x in properties if x is not None]) != 5: + print("invalid block structure") + return False + blockString = json.dumps(block, sort_keys=True) + return Blockchain.valid_proof(blockString, proof) + +# Instantiate our Node +app = Flask(__name__) + +# Generate a globally unique address for this node +node_identifier = str(uuid4()).replace('-', '') + +# Instantiate the Blockchain +blockchain = Blockchain() + + +@app.route('/mine', methods=['POST']) +def mine(): + jsonStr = request.data.decode("utf-8") + incomingMinedBlock = json.loads(jsonStr) + newProof = incomingMinedBlock.get("proof", None) + clientID = incomingMinedBlock.get("id", None) + if newProof is None or clientID is None: + return jsonify({"error": "Invalid proof info"}), 400 + newProof = int(newProof) + + if Blockchain.valid_proof_block(blockchain.last_block, newProof): + # successful = add new block and return message indicating success + previousHash = blockchain.hash(blockchain.last_block) + newBlock = blockchain.new_block(newProof, previousHash) + response = { + "status": "success", + "block": newBlock + } + return jsonify(response), 200 + else: + response = { + "status": "failure", + } + return jsonify(response), 401 + +@app.route('/chain', methods=['GET']) +def full_chain(): + response = { + # Return the chain and its current length + 'chain': blockchain.chain, + 'length': len(blockchain.chain), + } + return jsonify(response), 200 + + +@app.route('/lastblock', methods=['GET']) +def lastBlock(): + return jsonify(blockchain.last_block), 200 + +@app.route("/difficulty", methods=["GET"]) +def difficulty(): + return jsonify(blockchain.difficulty), 200 + +# Run the program on port 5000 +if __name__ == '__main__': + app.run(host='0.0.0.0', port=5000) diff --git a/client_mining_p/endpoints.paw b/client_mining_p/endpoints.paw new file mode 100644 index 00000000..9319c8f3 Binary files /dev/null and b/client_mining_p/endpoints.paw differ diff --git a/client_mining_p/miner.py b/client_mining_p/miner.py index 8e211b88..435924b1 100644 --- a/client_mining_p/miner.py +++ b/client_mining_p/miner.py @@ -3,9 +3,11 @@ import sys import json +import time +import random -def proof_of_work(block): +def proof_of_work(block, iterations, difficulty): """ Simple Proof of Work Algorithm Stringify the block and look for a proof. @@ -13,10 +15,15 @@ def proof_of_work(block): in an effort to find a number that is a valid proof :return: A valid proof for the provided block """ - pass + blockString = json.dumps(block, sort_keys=True) + for i in range(iterations): + proof = int(random.random() * 100000000) + if valid_proof(blockString, proof, difficulty): + return proof + return None -def valid_proof(block_string, proof): +def valid_proof(block_string, proof, difficulty): """ Validates the Proof: Does hash(block_string, proof) contain 6 leading zeroes? Return true if the proof is valid @@ -27,44 +34,80 @@ def valid_proof(block_string, proof): correct number of leading zeroes. :return: True if the resulting hash is a valid proof, False otherwise """ - pass + guess = f"{block_string}{proof}".encode() + guessHash = hashlib.sha256(guess).hexdigest() + return guessHash[:difficulty] == "0" * difficulty +def getLastblock(): + r = requests.get(url=node + "/lastblock") + diff = requests.get(url=node + "/difficulty") + # Handle non-json response + try: + data = r.json() + difficulty = diff.json() + except ValueError: + print("Error: Non-json response") + print("Response returned:") + print(r) + return None + + return (data, difficulty) + +def submitProof(new_proof): + # When found, POST it to the server {"proof": new_proof, "id": id} + post_data = {"proof": new_proof, "id": id} + + r = requests.post(url=node + "/mine", json=post_data) + try: + data = r.json() + except ValueError: + print("Error: Non-json response") + print("Response returned:") + print(r) + status = data.get("status", None) + if status is not None: + if status == "success": + return True + else: + print("block already solved") + return False + else: + return False + if __name__ == '__main__': # What is the server address? IE `python3 miner.py https://server.com/api/` + # if len(sys.argv) > 1: + # node = sys.argv[1] + # else: + node = "http://localhost:5000" + + # Load ID if len(sys.argv) > 1: - node = sys.argv[1] + id = sys.argv[1] else: - node = "http://localhost:5000" + f = open("my_id.txt", "r") + id = f.read() + f.close() - # Load ID - f = open("my_id.txt", "r") - id = f.read() print("ID is", id) - f.close() + + coins = 0 # Run forever until interrupted while True: - r = requests.get(url=node + "/last_block") - # Handle non-json response - try: - data = r.json() - except ValueError: - print("Error: Non-json response") - print("Response returned:") - print(r) - break - - # TODO: Get the block from `data` and use it to look for a new proof - # new_proof = ??? + data = None + new_proof = None + while new_proof is None: + data, difficulty = getLastblock() + if data is None: + break + new_proof = proof_of_work(data, 1000000, difficulty) # When found, POST it to the server {"proof": new_proof, "id": id} post_data = {"proof": new_proof, "id": id} - r = requests.post(url=node + "/mine", json=post_data) - data = r.json() - - # TODO: If the server responds with a 'message' 'New Block Forged' - # add 1 to the number of coins mined and print it. Otherwise, - # print the message from the server. - pass + success = submitProof(new_proof) + if success: + coins += 1 + print(f"my coins: {coins}") diff --git a/client_mining_p/my_id.txt b/client_mining_p/my_id.txt index 757227a3..2d7f4af8 100644 --- a/client_mining_p/my_id.txt +++ b/client_mining_p/my_id.txt @@ -1 +1 @@ -your-name-here +michael \ No newline at end of file