diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..0384585 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,55 @@ +{ + "files.associations": { + "cctype": "cpp", + "clocale": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "array": "cpp", + "atomic": "cpp", + "*.tcc": "cpp", + "chrono": "cpp", + "codecvt": "cpp", + "cstdint": "cpp", + "deque": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "filesystem": "cpp", + "functional": "cpp", + "iterator": "cpp", + "map": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "new": "cpp", + "ostream": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "typeinfo": "cpp", + "bit": "cpp", + "cmath": "cpp" + } +} \ No newline at end of file diff --git a/SOLUTION.md b/SOLUTION.md new file mode 100644 index 0000000..918809f --- /dev/null +++ b/SOLUTION.md @@ -0,0 +1,14 @@ +# Design Approach + +Steps invloved: +* Read all the transactions +* Look for the best transactions, that is transactions that give maximum txn fee: + * How to do this? +* Validate those transactions +* If any of them is invalid, look for the next best transaction not included in the block + +# Implementation Details + +# Results and Performance + +# Conclusion \ No newline at end of file diff --git a/bin/main b/bin/main new file mode 100755 index 0000000..c6cb55f Binary files /dev/null and b/bin/main differ diff --git a/run.sh b/run.sh old mode 100644 new mode 100755 index 721aeb2..ee73d79 --- a/run.sh +++ b/run.sh @@ -1 +1,2 @@ -# Update this file to run your own code \ No newline at end of file +g++ src/main.cpp -o bin/main -std=c++17 -ljsoncpp -lssl -lcrypto +bin/main \ No newline at end of file diff --git a/src/crypto.h b/src/crypto.h new file mode 100644 index 0000000..3fe95c9 --- /dev/null +++ b/src/crypto.h @@ -0,0 +1,39 @@ +#ifndef CRYPTO_H +#define CRYPTO_H + +#include +#include +#include +#include + +void sha256(const char *string, char outputBuffer[65]) +{ + unsigned char hash[SHA256_DIGEST_LENGTH]; + SHA256_CTX sha256; + SHA256_Init(&sha256); + SHA256_Update(&sha256, string, strlen(string)); + SHA256_Final(hash, &sha256); + int i = 0; + for(i = 0; i < SHA256_DIGEST_LENGTH; i++) + { + sprintf(outputBuffer + (i * 2), "%02x", hash[i]); + } + outputBuffer[64] = 0; +} + +void rpmd160(const char *string, char outputBuffer[41]) +{ + unsigned char hash[RIPEMD160_DIGEST_LENGTH]; + RIPEMD160_CTX ripemd; + RIPEMD160_Init(&ripemd); + RIPEMD160_Update(&ripemd, string, strlen(string)); + RIPEMD160_Final(hash, &ripemd); + int i = 0; + for(i = 0; i < RIPEMD160_DIGEST_LENGTH; i++) + { + sprintf(outputBuffer + (i * 2), "%02x", hash[i]); + } + outputBuffer[40] = 0; +} + +#endif // CRYPTO_H \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..380f588 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#include +#include "script.h" +using namespace std; + +int main() { + // vector transactions; // Vector to store all transactions + + // // Iterate through all files in the mempool directory and read the transactions + // for (auto &entry : filesystem::directory_iterator("mempool")) { + // ifstream txn_file(entry.path(), ifstream::binary); + // Json::Value txn; + // txn_file >> txn; + // bool check = true; + // for (auto &inp : txn["vin"]) { + // if (inp["prevout"]["scriptpubkey_type"] != "p2pkh"){ + // check = false; + // break; + // } + // } + // if (check) cout << verify_txn(txn) << '\n' << endl; + // // transactions.push_back(txn); + // } + + // set s; + // for (auto &txn : transactions) { + // for (auto &inp : txn["vin"]) { + // if (inp["prevout"]["scriptpubkey_type"] == "p2pkh"){ + // // cout << inp["prevout"]["scriptpubkey_asm"].asString() << endl; + // vector ops = getOps(inp["prevout"]["scriptpubkey_asm"].asString()); + // // cout << ops[0] << " " << ops[1] << " " << ops[2] << " " << ops[4] << " " << ops[5] << endl; + // s.insert(ops[0] + " " + ops[1] + " " + ops[2] + " " + ops[4] + " " + ops[5]); + // // s.insert(ops.size()); + // } + // } + // } + + // for (auto &i : s) { + // cout << i << endl; + // } + + ifstream txn_file("mempool/ff907975dc0cfa299e908e5fba6df56c764866d9a9c22828824c28b8e4511320.json", ifstream::binary); + Json::Value txn; + txn_file >> txn; + cout << verify_txn(txn) << endl; + + // char sha[65]; + // sha256(txn.toStyledString().c_str(), sha); + // cout << sha << endl; + + + + return 0; +} \ No newline at end of file diff --git a/src/script.h b/src/script.h new file mode 100644 index 0000000..5016c8a --- /dev/null +++ b/src/script.h @@ -0,0 +1,123 @@ +#ifndef SCRIPT_H +#define SCRIPT_H + +#include +#include +#include +#include +#include +#include "crypto.h" +#include +#include +#include +using namespace std; + +std::vector getOps(std::string asmScript) { + std::vector ops; + + while (asmScript.find(" ") != std::string::npos) { + std::string op = asmScript.substr(0, asmScript.find(" ")); + ops.push_back(op); + asmScript = asmScript.substr(asmScript.find(" ") + 1); + } + ops.push_back(asmScript); + + return ops; +} + +EC_POINT* Hex_to_point_NID_secp256k1(char* str) { + EC_KEY* ecKey = EC_KEY_new_by_curve_name(NID_secp256k1); + const EC_GROUP* ecGroup = EC_KEY_get0_group(ecKey); + EC_POINT* ecPoint = EC_POINT_hex2point(ecGroup, str, NULL, NULL); + return ecPoint; +} + + +bool p2pkh_verify(std::vector scriptPubKeyOps, std::vector scriptSigOps, Json::Value txn) { + std::string sig = scriptSigOps[1]; + std::string pubKey = scriptSigOps[3]; + + std::string pkh = scriptPubKeyOps[3]; + + char sha[65], rpmd[41]; + sha256(pubKey.c_str(), sha); + rpmd160(sha, rpmd); + + cout << "RIPEMD160: " << rpmd << endl; + cout << "PKH: " << pkh << endl; + + if (rpmd == pkh) { + // Remove scriptsig and scriptsig_asm from txn + // cout << "Entered" << endl; + return true; + for (auto &inp : txn["vin"]) + inp["scriptsig"] = inp["scriptsig_asm"] = ""; + + char sha2[65]; + sha256(txn.toStyledString().c_str(), sha); + sha256(sha, sha2); + + // Verify sig with pubKey and txn hash using ecdsa + char key[pubKey.length()+1]; + sprintf(key, "%s", pubKey.c_str()); + EC_KEY* publicKey = EC_KEY_new_by_curve_name(NID_secp256k1); + EC_KEY_set_public_key(publicKey, Hex_to_point_NID_secp256k1(key)); + if (ECDSA_verify(0, (unsigned char*) sha2, strlen(sha2), (unsigned char*) sig.c_str(), strlen(sig.c_str()), publicKey) == 1) { + // cout << "Match!!" << endl; + return true; + } + } + + return false; +} + + +bool p2sh_verify(std::vector scriptPubKeyOps, std::vector scriptSigOps, Json::Value txn) { + +} + + +bool p2wpkh_verify(std::vector scriptPubKeyOps, std::vector scriptSigOps, Json::Value txn) { + +} + + +bool p2wsh_verify(std::vector scriptPubKeyOps, std::vector scriptSigOps, Json::Value txn) { + +} + + +bool p2tr_verify(std::vector scriptPubKeyOps, std::vector scriptSigOps, Json::Value txn) { + +} + + +bool verify_txn(Json::Value &txn) { + bool valid = true; + + for (auto &inp : txn["vin"]) { + std::vector scriptPubKeyOps = getOps(inp["prevout"]["scriptpubkey_asm"].asString()); + std::vector scriptSigOps = getOps(inp["scriptsig_asm"].asString()); + std::string scriptPubKeyType = inp["prevout"]["scriptpubkey_type"].asString(); + + if (scriptPubKeyType == "p2pkh") + valid = p2pkh_verify(scriptPubKeyOps, scriptSigOps, txn); + else if (scriptPubKeyType == "p2sh") + valid = p2sh_verify(scriptPubKeyOps, scriptSigOps, txn); + else if (scriptPubKeyType == "p2wpkh") + valid = p2wpkh_verify(scriptPubKeyOps, scriptSigOps, txn); + else if (scriptPubKeyType == "p2wsh") + valid = p2wsh_verify(scriptPubKeyOps, scriptSigOps, txn); + else if (scriptPubKeyType == "p2tr") + valid = p2tr_verify(scriptPubKeyOps, scriptSigOps, txn); + else + return false; + + if (!valid) + return false; + } + + return true; +} + +#endif // SCRIPT_H \ No newline at end of file