From 0b4844216ac89cb461de6af081032ccfc90422aa Mon Sep 17 00:00:00 2001 From: tas-indranil Date: Sun, 3 Sep 2023 06:09:19 +0530 Subject: [PATCH 1/3] created a coinbase transaction, added a new api for flask --- .../Backend/API/Client_calls/BaseCurl.php | 2 +- .../API/Client_calls/PluginHelperAPI.php | 22 ++ Blockchain/Backend/core/Blockchain.php | 10 +- Blockchain/Backend/core/Script.php | 21 ++ .../Backend/core/transactions/Coinbase.php | 130 ++++++++ Blockchain/Backend/core/transactions/Tx.php | 71 +++++ Blockchain/Backend/core/transactions/TxIn.php | 17 ++ .../Backend/core/transactions/TxOut.php | 12 + Blockchain/Backend/util/util.php | 35 ++- .../{test.py => keyGenerate.py} | 10 +- Blockchain/Python_Package/main.py | 45 +++ Blockchain/Python_Package/util.py | 40 ++- Blockchain/data/blockchain | 285 +++++++++++++++--- 13 files changed, 639 insertions(+), 61 deletions(-) create mode 100644 Blockchain/Backend/API/Client_calls/PluginHelperAPI.php create mode 100644 Blockchain/Backend/core/Script.php create mode 100644 Blockchain/Backend/core/transactions/Coinbase.php create mode 100644 Blockchain/Backend/core/transactions/Tx.php create mode 100644 Blockchain/Backend/core/transactions/TxIn.php create mode 100644 Blockchain/Backend/core/transactions/TxOut.php rename Blockchain/Python_Package/{test.py => keyGenerate.py} (88%) create mode 100644 Blockchain/Python_Package/main.py diff --git a/Blockchain/Backend/API/Client_calls/BaseCurl.php b/Blockchain/Backend/API/Client_calls/BaseCurl.php index e347860..fb91d6a 100644 --- a/Blockchain/Backend/API/Client_calls/BaseCurl.php +++ b/Blockchain/Backend/API/Client_calls/BaseCurl.php @@ -1,5 +1,5 @@ coinbaseTransaction(); + $merkleRoot = ' '; $bits = 'ffff001f'; $blockheader = new BlockHeader($GLOBALS['VERSION'], $prevBlockHash, $merkleRoot, $timestamp, $bits); $blockheader->mine(); - $block = new Block($BlockHeight, 1, (array)$blockheader, 1, $Transaction); + $block = new Block($BlockHeight, 1, (array)$blockheader, 1, $coinbaseTx); +// print_r((array)$block); +// die(); $this->writeOnDisk((array)$block); } diff --git a/Blockchain/Backend/core/Script.php b/Blockchain/Backend/core/Script.php new file mode 100644 index 0000000..5bc00f1 --- /dev/null +++ b/Blockchain/Backend/core/Script.php @@ -0,0 +1,21 @@ +cmds = []; + } else { + $this->cmds = $cmds; + } + } + + public static function p2pkhScript($h160) + { + // Takes a hash160 and returns the p2 public key hash ScriptPubKey + $script = new Script([0x76, 0xA9, $h160, 0x88, 0xAC]); + return $script; + } +} \ No newline at end of file diff --git a/Blockchain/Backend/core/transactions/Coinbase.php b/Blockchain/Backend/core/transactions/Coinbase.php new file mode 100644 index 0000000..4ba83fb --- /dev/null +++ b/Blockchain/Backend/core/transactions/Coinbase.php @@ -0,0 +1,130 @@ +blockHeightIntLittleEndian = intToLittleEndian($blockHeight, bytesNeeded($blockHeight)); + } + + public function coinbaseTransaction() { + $prevTx = hex2bin(ZERO_HASH); + $prevIndex = 0xFFFFFFFF; + + $txIns = []; + $txIns[] = new TxIn($prevTx, $prevIndex); + $txIns[0]->scriptSig->cmds[] = $this->blockHeightIntLittleEndian; + + $txOuts = []; + $targetAmount = REWARD * 100000000; + $hexValue = $this->decodeBase58API(MINER_ADDRESS); + $targetH160 = $hexValue; + $targetScript = Script::p2pkhScript($targetH160); + $txOuts[] = new TxOut($targetAmount, $targetScript); + + return new Tx(1, $txIns, $txOuts, 0); + } + + public function decodeBase58API($value) + { + $address = PluginHelperAPI::$clientAddress; + $url = $address."get_decode_base58"; + $ch = curl_init($url); + $data = json_encode(array( + "value" => $value + )); + $val = PluginHelperAPI::curlSkeletonIfDataSend($ch, "POST", $data); + $data = json_decode($val['data'], true); + return $data['byte_data']; + } + +} + +//$address = PluginHelperAPI::$clientAddress; +//$url = $address."get_decode_base58"; +//$ch = curl_init($url); +//$data = json_encode(array( +// "value" => "1K3if2mFojLAWVtdD1eeYYKNVCwghpBvgb" +//)); +//$val = PluginHelperAPI::curlSkeletonIfDataSend($ch, "POST", $data); +//$data = json_decode($val['data'], true); +//echo "\n\n"; +//print_r($data['byte_data']); +//function decodeBase58API($value) +//{ +// $address = PluginHelperAPI::$clientAddress; +// $url = $address . "get_decode_base58"; +// $ch = curl_init($url); +// $data = json_encode(array( +// "value" => $value +// )); +// $val = PluginHelperAPI::curlSkeletonIfDataSend($ch, "POST", $data); +// $data = json_decode($val['data'], true); +// return $data['byte_data']; +//} +// +//$data = decodeBase58API("1K3if2mFojLAWVtdD1eeYYKNVCwghpBvgb"); +//echo "\n\n"; +//print_r($data); +//echo "\n\n"; +// +// +//$binaryData = hex2bin($data); +//print_r($binaryData); +//echo "\n\n"; +// +//// Perform operations on the binary data (if needed) +// +//// Convert the binary data back to a hexadecimal string +//$resultHexadecimal = bin2hex($binaryData); +// +//// Output the result +//echo $resultHexadecimal; + +////$hexString = $data; +////$byteString = 'b"' . implode('\x', str_split($hexString, 2)) . '"'; +//$byteString = hex2bin($data); +//$formattedBinary = 'b"'; +//foreach (str_split($byteString) as $byte) { +// $formattedBinary .= '\x' . bin2hex($byte); +//} +//$formattedBinary .= '",'; +// +//echo $formattedBinary; +//echo "\n\n"; +// +//$hexString = ''; +//$matches = []; +//if (preg_match('/b"(.+)",/', $formattedBinary, $matches)) { +// $hexBytes = explode('\x', $matches[1]); +// foreach ($hexBytes as $hexByte) { +// $hexString .= chr(hexdec($hexByte)); +// } +// $hexString = bin2hex($hexString); +// echo $hexString; +//} else { +// echo "Invalid format."; +//} +//echo "\n\n"; +// +//$hexString = ''; +//$matches = []; +// +//if (preg_match('/b"(.+)",/', $formattedBinary, $matches)) { +// $hexBytes = explode('\x', $matches[1]); +// foreach ($hexBytes as $hexByte) { +// $hexString .= bin2hex(hex2bin($hexByte)); +// } +// echo $hexString; +//} else { +// echo "Invalid format."; +//} \ No newline at end of file diff --git a/Blockchain/Backend/core/transactions/Tx.php b/Blockchain/Backend/core/transactions/Tx.php new file mode 100644 index 0000000..aa94bb6 --- /dev/null +++ b/Blockchain/Backend/core/transactions/Tx.php @@ -0,0 +1,71 @@ +version = $version; + $this->txIns = $txIns; + $this->txOuts = $txOuts; + $this->locktime = $locktime; + } + + public function serialize() { + $result = intToLittleEndian($this->version, 4); + $result .= count($this->txIns); + + // Add serialization logic here + + return $result; + } + + public function isCoinbase() { + if (count($this->txIns) !== 1) { + return false; + } + + $firstInput = $this->txIns[0]; + if ($firstInput->prevTx !== hex2bin(ZERO_HASH)) { + return false; + } + + if ($firstInput->prevIndex !== 0xFFFFFFFF) { + return false; + } + + return true; + } + + public function toDict() { + // Convert Transaction Input to dict + foreach ($this->txIns as $txIndex => $txIn) { + if ($this->isCoinbase()) { + $txIn->scriptSig->cmds[0] = littleEndianToInt($txIn->scriptSig->cmds[0]); + } + + $txIn->prevTx = bin2hex($txIn->prevTx); + + foreach ($txIn->scriptSig->cmds as $index => $cmd) { + if (is_string($cmd)) { + $txIn->scriptSig->cmds[$index] = bin2hex($cmd); + } + } + + $txIn->scriptSig = (array) $txIn->scriptSig; + $this->txIns[$txIndex] = (array) $txIn; + } + + // Convert Transaction Output to dict + foreach ($this->txOuts as $index => $txOut) { + $txOut->scriptPubkey->cmds[2] = bin2hex($txOut->scriptPubkey->cmds[2]); + $txOut->scriptPubkey = (array) $txOut->scriptPubkey; + $this->txOuts[$index] = (array) $txOut; + } + + return (array) $this; + } +} \ No newline at end of file diff --git a/Blockchain/Backend/core/transactions/TxIn.php b/Blockchain/Backend/core/transactions/TxIn.php new file mode 100644 index 0000000..261b88b --- /dev/null +++ b/Blockchain/Backend/core/transactions/TxIn.php @@ -0,0 +1,17 @@ +prevTx = $prevTx; + $this->prevIndex = $prevIndex; + $this->scriptSig = $scriptSig ?? new Script(); + $this->sequence = $sequence; + } +} \ No newline at end of file diff --git a/Blockchain/Backend/core/transactions/TxOut.php b/Blockchain/Backend/core/transactions/TxOut.php new file mode 100644 index 0000000..81279f2 --- /dev/null +++ b/Blockchain/Backend/core/transactions/TxOut.php @@ -0,0 +1,12 @@ +amount = $amount; + $this->scriptPubkey = $scriptPubkey; + } +} \ No newline at end of file diff --git a/Blockchain/Backend/util/util.php b/Blockchain/Backend/util/util.php index 9bd1b95..d116b70 100644 --- a/Blockchain/Backend/util/util.php +++ b/Blockchain/Backend/util/util.php @@ -10,10 +10,33 @@ function hash160($data) { return hash('ripemd160', $sha256Hash, true); } -// Example usage -$input = 'some data to hash'; -$hashed256 = hash256($input); -$hashed160 = hash160($input); +function intToLittleEndian($number, $length) +{ + // Use 'V' format for little-endian and unsigned long + $value = pack('V', $number); + return bin2hex($value); +} + +function bytesNeeded($n) +{ + if ($n == 0) { + return 1; + } + return intval(log($n, 256)) + 1; +} -echo "Hashed 256: " . bin2hex($hashed256) . PHP_EOL; -echo "Hashed 160: " . bin2hex($hashed160) . PHP_EOL; \ No newline at end of file +function littleEndianToInt($b) +{ + // Reverse the byte array and convert it to an integer + $reversedBytes = array_reverse(str_split($b)); + $littleEndian = implode('', $reversedBytes); + return hexdec(bin2hex($littleEndian)); +} + +// Example usage +//$input = 'some data to hash'; +//$hashed256 = hash256($input); +//$hashed160 = hash160($input); +// +//echo "Hashed 256: " . bin2hex($hashed256) . PHP_EOL; +//echo "Hashed 160: " . bin2hex($hashed160) . PHP_EOL; \ No newline at end of file diff --git a/Blockchain/Python_Package/test.py b/Blockchain/Python_Package/keyGenerate.py similarity index 88% rename from Blockchain/Python_Package/test.py rename to Blockchain/Python_Package/keyGenerate.py index f2de86f..f0437a7 100644 --- a/Blockchain/Python_Package/test.py +++ b/Blockchain/Python_Package/keyGenerate.py @@ -1,13 +1,9 @@ -from flask import Flask, jsonify import secrets from EllepticCurve.EllepticCurve import Sha256Point from util import hash160, hash256 -app = Flask(__name__) - -@app.route('/generate_keys', methods=['GET']) -def generate_keys(): +def generatePrivateKeyPublicAddress(): Gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798 Gy = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8 @@ -53,7 +49,3 @@ def generate_keys(): PublicAddress = prefix + result return {"privateKey": privateKey, "publicAddress": PublicAddress} - - -if __name__ == '__main__': - app.run(debug=True) diff --git a/Blockchain/Python_Package/main.py b/Blockchain/Python_Package/main.py new file mode 100644 index 0000000..271220f --- /dev/null +++ b/Blockchain/Python_Package/main.py @@ -0,0 +1,45 @@ +from flask import Flask, jsonify, request +from keyGenerate import generatePrivateKeyPublicAddress +from util import bytes_needed, decode_base58, little_endian_to_int, int_to_little_endian +import json +import sys + + +app = Flask(__name__) + + +@app.route('/generate_keys', methods=['GET']) +def generate_keys(): + result = generatePrivateKeyPublicAddress() + return result + + +# ====================================================================================================================== + +@app.route('/get_bytes_needed', methods=['POST']) +def get_bytes_needed(): + data = request.get_json() + if 'value' not in data: + return jsonify({'error': 'Missing values'}), 400 + val = int(data['value']) + result = bytes_needed(val) + return jsonify({"result": result}), 201 + + +# ====================================================================================================================== + +@app.route('/get_decode_base58', methods=['POST']) +def get_decode_base58(): + data = request.get_json() + if 'value' not in data: + return jsonify({'error': 'Missing values'}), 400 + byte_data = decode_base58(data['value']) + hex_data = byte_data.hex() + response = { + 'byte_data': hex_data + } + return jsonify(response) + + +if __name__ == '__main__': + app.run(debug=True) diff --git a/Blockchain/Python_Package/util.py b/Blockchain/Python_Package/util.py index 48739d1..88de17c 100644 --- a/Blockchain/Python_Package/util.py +++ b/Blockchain/Python_Package/util.py @@ -1,6 +1,9 @@ import hashlib from Crypto.Hash import RIPEMD160 from hashlib import sha256 +from math import log +from EllepticCurve.EllepticCurve import BASE58_ALPHABET + def hash256(s): @@ -9,4 +12,39 @@ def hash256(s): def hash160(s): - return RIPEMD160.new(sha256(s).digest()).digest() \ No newline at end of file + return RIPEMD160.new(sha256(s).digest()).digest() + + +def bytes_needed(n: int): + """ Returns byte length """ + if n == 0: + return 1 + return int(log(n, 256)) + 1 + + +def int_to_little_endian(n: int, length): + """ Takes integer and return the little endian byte of length """ + return n.to_bytes(length, 'little') + + +def little_endian_to_int(b): + """ takes bit AND RETURNS AN INTEGER """ + return int.from_bytes(b, 'little') + + +def decode_base58(s): + num = 0 + for c in s: + num *= 58 + num += BASE58_ALPHABET.index(c) + + combined = num.to_bytes(25, byteorder='big') + checksum = combined[-4:] + + if hash256(combined[:-4])[:4] != checksum: + raise ValueError(f'Bad address {checksum} {hash256(combined[:-4])[:4]}') + + value = combined[1:-4] + return value + +# b"\xc5\xf5\xdeS\x1f\xfb\xc9G\x16G\x81E\x9b\x06!\xda\xb5'\xee," diff --git a/Blockchain/data/blockchain b/Blockchain/data/blockchain index a2b05ae..149a749 100644 --- a/Blockchain/data/blockchain +++ b/Blockchain/data/blockchain @@ -4,104 +4,307 @@ "Blocksize": 1, "BlockHeader": { "bits": "ffff001f", - "timestamp": 1692918870, - "merkleRoot": "01d3c8ffac385f49854b12bc69248645efddb80a0435dd09631643bdc605d1d1", + "timestamp": 1693700421, + "merkleRoot": " ", "prevBlockHash": "0000000000000000000000000000000000000000000000000000000000000000", "version": 1, - "nonce": 57706, - "blockHash": "0000d0f7be9722a4d33a1147995f54e00dd09304c3de35b86abf3c73d493f269" + "nonce": 85333, + "blockHash": "0000eb34365c3f89239ed92b31ec45c079f15f53d980464a15d0d474ddc25e22" }, "TxCount": 1, - "Txs": "Code Architect sent 0 Bitcoins to Indranil" + "Txs": { + "locktime": 0, + "txOuts": [ + { + "amount": 5000000000, + "scriptPubkey": { + "cmds": [ + 118, + 169, + "c5f5de531ffbc947164781459b0621dab527ee2c", + 136, + 172 + ] + } + } + ], + "txIns": [ + { + "prevTx": "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", + "prevIndex": 4294967295, + "scriptSig": { + "cmds": [ + "00000000" + ] + }, + "sequence": 4294967295 + } + ], + "version": 1 + } }, { "Height": 1, "Blocksize": 1, "BlockHeader": { "bits": "ffff001f", - "timestamp": 1692918885, - "merkleRoot": "ede8645e1159205c35365fc6b765fbea7acab3d30d83f2094e87b1dc2829b69b", - "prevBlockHash": "0000d0f7be9722a4d33a1147995f54e00dd09304c3de35b86abf3c73d493f269", + "timestamp": 1693700445, + "merkleRoot": " ", + "prevBlockHash": "0000eb34365c3f89239ed92b31ec45c079f15f53d980464a15d0d474ddc25e22", "version": 1, - "nonce": 30400, - "blockHash": "0000145cbce04e57681a3492198f05ca5f68f730d2a49ced6f62a22e1e0fb89e" + "nonce": 6742, + "blockHash": "000045245bb909427902c6b9eb8ee3a6ddbf3bd9e143cfbba9905e34fed8721e" }, "TxCount": 1, - "Txs": "Code Architect sent 1 Bitcoins to Indranil" + "Txs": { + "locktime": 0, + "txOuts": [ + { + "amount": 5000000000, + "scriptPubkey": { + "cmds": [ + 118, + 169, + "c5f5de531ffbc947164781459b0621dab527ee2c", + 136, + 172 + ] + } + } + ], + "txIns": [ + { + "prevTx": "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", + "prevIndex": 4294967295, + "scriptSig": { + "cmds": [ + "01000000" + ] + }, + "sequence": 4294967295 + } + ], + "version": 1 + } }, { "Height": 2, "Blocksize": 1, "BlockHeader": { "bits": "ffff001f", - "timestamp": 1692918893, - "merkleRoot": "ee3d44bff24ade0bd29fbf90bcfa1a8a2ef2c991a92bf92e8e8d7bf85cf75e30", - "prevBlockHash": "0000145cbce04e57681a3492198f05ca5f68f730d2a49ced6f62a22e1e0fb89e", + "timestamp": 1693700447, + "merkleRoot": " ", + "prevBlockHash": "000045245bb909427902c6b9eb8ee3a6ddbf3bd9e143cfbba9905e34fed8721e", "version": 1, - "nonce": 57819, - "blockHash": "0000b8ef9e602a62196ef75a05dc898ac1e599b4cfe69fd23fcef020ffe70e82" + "nonce": 21123, + "blockHash": "00008c920a4eb0fb40d93006e94f7c675e69b8186500341ded65bb23eb789baf" }, "TxCount": 1, - "Txs": "Code Architect sent 2 Bitcoins to Indranil" + "Txs": { + "locktime": 0, + "txOuts": [ + { + "amount": 5000000000, + "scriptPubkey": { + "cmds": [ + 118, + 169, + "c5f5de531ffbc947164781459b0621dab527ee2c", + 136, + 172 + ] + } + } + ], + "txIns": [ + { + "prevTx": "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", + "prevIndex": 4294967295, + "scriptSig": { + "cmds": [ + "02000000" + ] + }, + "sequence": 4294967295 + } + ], + "version": 1 + } }, { "Height": 3, "Blocksize": 1, "BlockHeader": { "bits": "ffff001f", - "timestamp": 1692918912, - "merkleRoot": "d0249e654794fa76a823925895732057dc5c51075131f4784a65d31f93754113", - "prevBlockHash": "0000b8ef9e602a62196ef75a05dc898ac1e599b4cfe69fd23fcef020ffe70e82", + "timestamp": 1693700454, + "merkleRoot": " ", + "prevBlockHash": "00008c920a4eb0fb40d93006e94f7c675e69b8186500341ded65bb23eb789baf", "version": 1, - "nonce": 91549, - "blockHash": "000046cfcf21c1ef5ae5abdc09ee2f5d2a95dc4b19dea21e312b1ce3f8cc2718" + "nonce": 69161, + "blockHash": "0000bba05acf5a9f312a86f9e3eaf5da7ef1ff49437422c96c344c9cbf8042f9" }, "TxCount": 1, - "Txs": "Code Architect sent 3 Bitcoins to Indranil" + "Txs": { + "locktime": 0, + "txOuts": [ + { + "amount": 5000000000, + "scriptPubkey": { + "cmds": [ + 118, + 169, + "c5f5de531ffbc947164781459b0621dab527ee2c", + 136, + 172 + ] + } + } + ], + "txIns": [ + { + "prevTx": "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", + "prevIndex": 4294967295, + "scriptSig": { + "cmds": [ + "03000000" + ] + }, + "sequence": 4294967295 + } + ], + "version": 1 + } }, { "Height": 4, "Blocksize": 1, "BlockHeader": { "bits": "ffff001f", - "timestamp": 1692918942, - "merkleRoot": "3bf90cb05ba2fb3325fec0def457cd7cc6126b204c8963d4939350b2add27c6d", - "prevBlockHash": "000046cfcf21c1ef5ae5abdc09ee2f5d2a95dc4b19dea21e312b1ce3f8cc2718", + "timestamp": 1693700478, + "merkleRoot": " ", + "prevBlockHash": "0000bba05acf5a9f312a86f9e3eaf5da7ef1ff49437422c96c344c9cbf8042f9", "version": 1, - "nonce": 88482, - "blockHash": "00008541d660a151dc1d3d4ca81c5dd844c0c37b07e643322192eace6b5e50b7" + "nonce": 3234, + "blockHash": "00003b292ea96d5d4e24437df34d6c84dbc51110a7a3c415dc7f7ee37ce997bf" }, "TxCount": 1, - "Txs": "Code Architect sent 4 Bitcoins to Indranil" + "Txs": { + "locktime": 0, + "txOuts": [ + { + "amount": 5000000000, + "scriptPubkey": { + "cmds": [ + 118, + 169, + "c5f5de531ffbc947164781459b0621dab527ee2c", + 136, + 172 + ] + } + } + ], + "txIns": [ + { + "prevTx": "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", + "prevIndex": 4294967295, + "scriptSig": { + "cmds": [ + "04000000" + ] + }, + "sequence": 4294967295 + } + ], + "version": 1 + } }, { "Height": 5, "Blocksize": 1, "BlockHeader": { "bits": "ffff001f", - "timestamp": 1692918975, - "merkleRoot": "5957ff49fe734ffde6fb685fd313afff54a59671e98acab4f5c84fa8ded0b177", - "prevBlockHash": "00008541d660a151dc1d3d4ca81c5dd844c0c37b07e643322192eace6b5e50b7", + "timestamp": 1693700480, + "merkleRoot": " ", + "prevBlockHash": "00003b292ea96d5d4e24437df34d6c84dbc51110a7a3c415dc7f7ee37ce997bf", "version": 1, - "nonce": 8339, - "blockHash": "00005c7fd514f61cd3173a7cbd5fa54a0eb90b0ba28e9c442bc0a666fdb1dc71" + "nonce": 5138, + "blockHash": "000073e599f48019a1631952eb5879a4bc76aa570c1275a600303cac5f93a45e" }, "TxCount": 1, - "Txs": "Code Architect sent 5 Bitcoins to Indranil" + "Txs": { + "locktime": 0, + "txOuts": [ + { + "amount": 5000000000, + "scriptPubkey": { + "cmds": [ + 118, + 169, + "c5f5de531ffbc947164781459b0621dab527ee2c", + 136, + 172 + ] + } + } + ], + "txIns": [ + { + "prevTx": "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", + "prevIndex": 4294967295, + "scriptSig": { + "cmds": [ + "05000000" + ] + }, + "sequence": 4294967295 + } + ], + "version": 1 + } }, { "Height": 6, "Blocksize": 1, "BlockHeader": { "bits": "ffff001f", - "timestamp": 1692918978, - "merkleRoot": "fc73585acb5dfb029ad461c0a2caa7259d33e3e9c613eec7ea9926a7fdceb92c", - "prevBlockHash": "00005c7fd514f61cd3173a7cbd5fa54a0eb90b0ba28e9c442bc0a666fdb1dc71", + "timestamp": 1693700482, + "merkleRoot": " ", + "prevBlockHash": "000073e599f48019a1631952eb5879a4bc76aa570c1275a600303cac5f93a45e", "version": 1, - "nonce": 268283, - "blockHash": "0000210da7a197c7734b55f27751ecfdc7bb3f881bf49f230d5866625fd3dd54" + "nonce": 112657, + "blockHash": "00008cc0036e7f27a36175191f569ff8b6136718e729e15e3d7d9acdd82e2d9a" }, "TxCount": 1, - "Txs": "Code Architect sent 6 Bitcoins to Indranil" + "Txs": { + "locktime": 0, + "txOuts": [ + { + "amount": 5000000000, + "scriptPubkey": { + "cmds": [ + 118, + 169, + "c5f5de531ffbc947164781459b0621dab527ee2c", + 136, + 172 + ] + } + } + ], + "txIns": [ + { + "prevTx": "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", + "prevIndex": 4294967295, + "scriptSig": { + "cmds": [ + "06000000" + ] + }, + "sequence": 4294967295 + } + ], + "version": 1 + } } ] \ No newline at end of file From adc330fb9ee5c921ba28be6c3f0d93f80c0dfc70 Mon Sep 17 00:00:00 2001 From: tas-indranil Date: Tue, 12 Sep 2023 05:40:34 +0530 Subject: [PATCH 2/3] added merkleroot --- Blockchain/Backend/core/Blockchain.php | 2 +- .../Backend/core/transactions/Coinbase.php | 5 +- Blockchain/Backend/core/transactions/Tx.php | 45 ++- Blockchain/Backend/core/transactions/TxIn.php | 9 + .../Backend/core/transactions/TxOut.php | 9 +- Blockchain/Backend/util/util.php | 35 +- Blockchain/data/blockchain | 310 ------------------ 7 files changed, 93 insertions(+), 322 deletions(-) diff --git a/Blockchain/Backend/core/Blockchain.php b/Blockchain/Backend/core/Blockchain.php index 9ee0788..33e45b0 100644 --- a/Blockchain/Backend/core/Blockchain.php +++ b/Blockchain/Backend/core/Blockchain.php @@ -35,7 +35,7 @@ public function addBlock($BlockHeight, $prevBlockHash) { $timestamp = time(); $coinbaseInstance = new Coinbase($BlockHeight); $coinbaseTx = $coinbaseInstance->coinbaseTransaction(); - $merkleRoot = ' '; + $merkleRoot = $coinbaseTx->TxId; $bits = 'ffff001f'; $blockheader = new BlockHeader($GLOBALS['VERSION'], $prevBlockHash, $merkleRoot, $timestamp, $bits); $blockheader->mine(); diff --git a/Blockchain/Backend/core/transactions/Coinbase.php b/Blockchain/Backend/core/transactions/Coinbase.php index 4ba83fb..23c54eb 100644 --- a/Blockchain/Backend/core/transactions/Coinbase.php +++ b/Blockchain/Backend/core/transactions/Coinbase.php @@ -31,7 +31,10 @@ public function coinbaseTransaction() { $targetScript = Script::p2pkhScript($targetH160); $txOuts[] = new TxOut($targetAmount, $targetScript); - return new Tx(1, $txIns, $txOuts, 0); + $coinBaseTx = new Tx(1, $txIns, $txOuts, 0); + $coinBaseTx->TxId = $coinBaseTx->id(); + + return $coinBaseTx; } public function decodeBase58API($value) diff --git a/Blockchain/Backend/core/transactions/Tx.php b/Blockchain/Backend/core/transactions/Tx.php index aa94bb6..d711f93 100644 --- a/Blockchain/Backend/core/transactions/Tx.php +++ b/Blockchain/Backend/core/transactions/Tx.php @@ -1,5 +1,5 @@ locktime = $locktime; } + /** + * @throws Exception + */ public function serialize() { - $result = intToLittleEndian($this->version, 4); - $result .= count($this->txIns); + // Initialize an empty result string + $result = ""; + + // Serialize the version as a little-endian 4-byte integer + $result .= intToLittleEndian($this->version, 4); + + // Serialize the number of transaction inputs as a variable-length integer + $result .= encode_varint(count($this->tx_ins)); + + // Serialize each transaction input + foreach ($this->tx_ins as $tx_in) { + $result .= $tx_in->serialize(); + } + + // Serialize the number of transaction outputs as a variable-length integer + $result .= encode_varint(count($this->tx_outs)); - // Add serialization logic here + // Serialize each transaction output + foreach ($this->tx_outs as $tx_out) { + $result .= $tx_out->serialize(); + } + + // Serialize the locktime as a little-endian 4-byte integer + $result .= intToLittleEndian($this->locktime, 4); + // Return the serialized result return $result; } + public function id() { + // Human-readable Tx id + return $this->hash()->hex(); + } + + /** + * @throws Exception + */ + public function hash() { + // Binary Hash of serialization + return strrev(hash256($this->serialize())); + } + public function isCoinbase() { if (count($this->txIns) !== 1) { return false; diff --git a/Blockchain/Backend/core/transactions/TxIn.php b/Blockchain/Backend/core/transactions/TxIn.php index 261b88b..d7ddf39 100644 --- a/Blockchain/Backend/core/transactions/TxIn.php +++ b/Blockchain/Backend/core/transactions/TxIn.php @@ -14,4 +14,13 @@ public function __construct($prevTx, $prevIndex, $scriptSig = null, $sequence = $this->scriptSig = $scriptSig ?? new Script(); $this->sequence = $sequence; } + + public function serialize() + { + $result = strrev($this->prev_tx); + $result .= intToLittleEndian($this->prev_index, 4); + $result .= $this->script_sig->serialize(); + $result .= intToLittleEndian($this->sequence, 4); + return $result; + } } \ No newline at end of file diff --git a/Blockchain/Backend/core/transactions/TxOut.php b/Blockchain/Backend/core/transactions/TxOut.php index 81279f2..00d8e57 100644 --- a/Blockchain/Backend/core/transactions/TxOut.php +++ b/Blockchain/Backend/core/transactions/TxOut.php @@ -1,5 +1,5 @@ amount = $amount; $this->scriptPubkey = $scriptPubkey; } + + public function serialize() + { + $result = intToLittleEndian($this->amount, 8); + $result .= $this->script_pubkey->serialize(); + return $result; + } } \ No newline at end of file diff --git a/Blockchain/Backend/util/util.php b/Blockchain/Backend/util/util.php index d116b70..d064a7d 100644 --- a/Blockchain/Backend/util/util.php +++ b/Blockchain/Backend/util/util.php @@ -10,11 +10,15 @@ function hash160($data) { return hash('ripemd160', $sha256Hash, true); } -function intToLittleEndian($number, $length) -{ - // Use 'V' format for little-endian and unsigned long - $value = pack('V', $number); - return bin2hex($value); +function intToLittleEndian($n, $length) { + // Convert an integer to a little-endian byte string of a specified length + $result = ''; + for ($i = 0; $i < $length; $i++) { + $byte = $n & 0xFF; // Get the least significant byte + $result .= chr($byte); // Convert to a character and append to the result + $n >>= 8; // Shift the integer right by 8 bits + } + return $result; } function bytesNeeded($n) @@ -33,6 +37,27 @@ function littleEndianToInt($b) return hexdec(bin2hex($littleEndian)); } + +function encode_varint($i) { + if ($i < 0xFD) { + return chr($i); + } elseif ($i < 0x10000) { + return "\xFD" . intToLittleEndian($i, 2); + } elseif ($i < 0x100000000) { + return "\xFE" . intToLittleEndian($i, 4); + } elseif ($i < 0x10000000000000000) { + return "\xFF" . intToLittleEndian($i, 8); + } else { + throw new Exception("integer too large: $i"); + } +} + +//try { +// $encoded = encode_varint(500); +//} catch (Exception $e) { +//} +//echo bin2hex($encoded); + // Example usage //$input = 'some data to hash'; //$hashed256 = hash256($input); diff --git a/Blockchain/data/blockchain b/Blockchain/data/blockchain index 149a749..e69de29 100644 --- a/Blockchain/data/blockchain +++ b/Blockchain/data/blockchain @@ -1,310 +0,0 @@ -[ - { - "Height": 0, - "Blocksize": 1, - "BlockHeader": { - "bits": "ffff001f", - "timestamp": 1693700421, - "merkleRoot": " ", - "prevBlockHash": "0000000000000000000000000000000000000000000000000000000000000000", - "version": 1, - "nonce": 85333, - "blockHash": "0000eb34365c3f89239ed92b31ec45c079f15f53d980464a15d0d474ddc25e22" - }, - "TxCount": 1, - "Txs": { - "locktime": 0, - "txOuts": [ - { - "amount": 5000000000, - "scriptPubkey": { - "cmds": [ - 118, - 169, - "c5f5de531ffbc947164781459b0621dab527ee2c", - 136, - 172 - ] - } - } - ], - "txIns": [ - { - "prevTx": "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", - "prevIndex": 4294967295, - "scriptSig": { - "cmds": [ - "00000000" - ] - }, - "sequence": 4294967295 - } - ], - "version": 1 - } - }, - { - "Height": 1, - "Blocksize": 1, - "BlockHeader": { - "bits": "ffff001f", - "timestamp": 1693700445, - "merkleRoot": " ", - "prevBlockHash": "0000eb34365c3f89239ed92b31ec45c079f15f53d980464a15d0d474ddc25e22", - "version": 1, - "nonce": 6742, - "blockHash": "000045245bb909427902c6b9eb8ee3a6ddbf3bd9e143cfbba9905e34fed8721e" - }, - "TxCount": 1, - "Txs": { - "locktime": 0, - "txOuts": [ - { - "amount": 5000000000, - "scriptPubkey": { - "cmds": [ - 118, - 169, - "c5f5de531ffbc947164781459b0621dab527ee2c", - 136, - 172 - ] - } - } - ], - "txIns": [ - { - "prevTx": "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", - "prevIndex": 4294967295, - "scriptSig": { - "cmds": [ - "01000000" - ] - }, - "sequence": 4294967295 - } - ], - "version": 1 - } - }, - { - "Height": 2, - "Blocksize": 1, - "BlockHeader": { - "bits": "ffff001f", - "timestamp": 1693700447, - "merkleRoot": " ", - "prevBlockHash": "000045245bb909427902c6b9eb8ee3a6ddbf3bd9e143cfbba9905e34fed8721e", - "version": 1, - "nonce": 21123, - "blockHash": "00008c920a4eb0fb40d93006e94f7c675e69b8186500341ded65bb23eb789baf" - }, - "TxCount": 1, - "Txs": { - "locktime": 0, - "txOuts": [ - { - "amount": 5000000000, - "scriptPubkey": { - "cmds": [ - 118, - 169, - "c5f5de531ffbc947164781459b0621dab527ee2c", - 136, - 172 - ] - } - } - ], - "txIns": [ - { - "prevTx": "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", - "prevIndex": 4294967295, - "scriptSig": { - "cmds": [ - "02000000" - ] - }, - "sequence": 4294967295 - } - ], - "version": 1 - } - }, - { - "Height": 3, - "Blocksize": 1, - "BlockHeader": { - "bits": "ffff001f", - "timestamp": 1693700454, - "merkleRoot": " ", - "prevBlockHash": "00008c920a4eb0fb40d93006e94f7c675e69b8186500341ded65bb23eb789baf", - "version": 1, - "nonce": 69161, - "blockHash": "0000bba05acf5a9f312a86f9e3eaf5da7ef1ff49437422c96c344c9cbf8042f9" - }, - "TxCount": 1, - "Txs": { - "locktime": 0, - "txOuts": [ - { - "amount": 5000000000, - "scriptPubkey": { - "cmds": [ - 118, - 169, - "c5f5de531ffbc947164781459b0621dab527ee2c", - 136, - 172 - ] - } - } - ], - "txIns": [ - { - "prevTx": "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", - "prevIndex": 4294967295, - "scriptSig": { - "cmds": [ - "03000000" - ] - }, - "sequence": 4294967295 - } - ], - "version": 1 - } - }, - { - "Height": 4, - "Blocksize": 1, - "BlockHeader": { - "bits": "ffff001f", - "timestamp": 1693700478, - "merkleRoot": " ", - "prevBlockHash": "0000bba05acf5a9f312a86f9e3eaf5da7ef1ff49437422c96c344c9cbf8042f9", - "version": 1, - "nonce": 3234, - "blockHash": "00003b292ea96d5d4e24437df34d6c84dbc51110a7a3c415dc7f7ee37ce997bf" - }, - "TxCount": 1, - "Txs": { - "locktime": 0, - "txOuts": [ - { - "amount": 5000000000, - "scriptPubkey": { - "cmds": [ - 118, - 169, - "c5f5de531ffbc947164781459b0621dab527ee2c", - 136, - 172 - ] - } - } - ], - "txIns": [ - { - "prevTx": "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", - "prevIndex": 4294967295, - "scriptSig": { - "cmds": [ - "04000000" - ] - }, - "sequence": 4294967295 - } - ], - "version": 1 - } - }, - { - "Height": 5, - "Blocksize": 1, - "BlockHeader": { - "bits": "ffff001f", - "timestamp": 1693700480, - "merkleRoot": " ", - "prevBlockHash": "00003b292ea96d5d4e24437df34d6c84dbc51110a7a3c415dc7f7ee37ce997bf", - "version": 1, - "nonce": 5138, - "blockHash": "000073e599f48019a1631952eb5879a4bc76aa570c1275a600303cac5f93a45e" - }, - "TxCount": 1, - "Txs": { - "locktime": 0, - "txOuts": [ - { - "amount": 5000000000, - "scriptPubkey": { - "cmds": [ - 118, - 169, - "c5f5de531ffbc947164781459b0621dab527ee2c", - 136, - 172 - ] - } - } - ], - "txIns": [ - { - "prevTx": "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", - "prevIndex": 4294967295, - "scriptSig": { - "cmds": [ - "05000000" - ] - }, - "sequence": 4294967295 - } - ], - "version": 1 - } - }, - { - "Height": 6, - "Blocksize": 1, - "BlockHeader": { - "bits": "ffff001f", - "timestamp": 1693700482, - "merkleRoot": " ", - "prevBlockHash": "000073e599f48019a1631952eb5879a4bc76aa570c1275a600303cac5f93a45e", - "version": 1, - "nonce": 112657, - "blockHash": "00008cc0036e7f27a36175191f569ff8b6136718e729e15e3d7d9acdd82e2d9a" - }, - "TxCount": 1, - "Txs": { - "locktime": 0, - "txOuts": [ - { - "amount": 5000000000, - "scriptPubkey": { - "cmds": [ - 118, - 169, - "c5f5de531ffbc947164781459b0621dab527ee2c", - 136, - 172 - ] - } - } - ], - "txIns": [ - { - "prevTx": "\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000", - "prevIndex": 4294967295, - "scriptSig": { - "cmds": [ - "06000000" - ] - }, - "sequence": 4294967295 - } - ], - "version": 1 - } - } -] \ No newline at end of file From ee56e8b83677c04786fd2fdd5418239ee6e0f706 Mon Sep 17 00:00:00 2001 From: Indranil Samanta Date: Tue, 12 Sep 2023 05:44:26 +0530 Subject: [PATCH 3/3] Update README.md --- README.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 576900e..122acac 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,10 @@ # Blockchain with php -A personal project \ No newline at end of file +This is just a demo project just for concept purposes. Please don't use this in production. Reasons not to use PHP for blockchain development or in production: + +**Security**: Blockchain systems require a high level of security because they deal with valuable assets and transactions. PHP, while it can be secure when used correctly, has had security vulnerabilities in the past. Languages like C++ and Rust have better memory management features that can help prevent common vulnerabilities like buffer overflows. + +**Community and Ecosystem**: Blockchain development relies heavily on available libraries, tools, and an active community for support. PHP has a limited ecosystem for blockchain development compared to languages like Python, JavaScript, or Solidity (Ethereum's smart contract language). + +**Concurrency**: Many blockchain systems require high levels of concurrency and parallelism. PHP's architecture is typically designed around a request-response model, which may not be well-suited for handling the concurrent nature of blockchain networks. + +**Blockchain-specific Libraries**: Most blockchain networks have their own specific libraries and APIs for development. While there might be PHP libraries for blockchain integration, they are not as prevalent or well-maintained as libraries in other languages. pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy