diff --git a/src/server/poolserver/Server/Server.cpp b/src/server/poolserver/Server/Server.cpp index 00a3637..5cdeddc 100644 --- a/src/server/poolserver/Server/Server.cpp +++ b/src/server/poolserver/Server/Server.cpp @@ -34,8 +34,31 @@ int Server::Run() sLog.Info(LOG_SERVER, "Server is starting..."); //InitDatabase(); + std::vector test = Util::ASCIIToBin("4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); + sLog.Info(LOG_SERVER, "Hash: %s", Util::BinToASCII(Crypto::SHA256D(test)).c_str()); + sLog.Info(LOG_SERVER, "RevHash: %s", Util::BinToASCII(Crypto::SHA256D(Util::Reverse(test))).c_str()); - ByteBuffer buf(Util::ASCIIToBin("01000000010c432f4fb3e871a8bda638350b3d5c698cf431db8d6031b53e3fb5159e59d4a90000000000ffffffff0100f2052a010000001976a9143744841e13b90b4aca16fe793a7f88da3a23cc7188ac00000000")); + Bitcoin::Block block; + + ByteBuffer buf(Util::ASCIIToBin("01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4d04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73ffffffff0100f2052a01000000434104678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5fac00000000")); + Bitcoin::Transaction trans; + buf >> trans; + sLog.Info(LOG_SERVER, "Version: %u", trans.version); + sLog.Info(LOG_SERVER, "Inputs: %u", trans.in.size()); + sLog.Info(LOG_SERVER, "PrevOut: %s", Util::BinToASCII(trans.in[0].prevout.hash).c_str()); + sLog.Info(LOG_SERVER, "PrevOutn: %u", trans.in[0].prevout.n); + sLog.Info(LOG_SERVER, "ScriptSig: %s", Util::BinToASCII(trans.in[0].script.script).c_str()); + sLog.Info(LOG_SERVER, "Inn: %u", trans.in[0].n); + sLog.Info(LOG_SERVER, "Outputs: %u", trans.out.size()); + sLog.Info(LOG_SERVER, "Value: %i", trans.out[0].value); + sLog.Info(LOG_SERVER, "PubSig: %s", Util::BinToASCII(trans.out[0].scriptPubKey.script).c_str()); + sLog.Info(LOG_SERVER, "LockTime: %u", trans.lockTime); + block.tx.resize(1); + block.tx[0] = trans; + block.BuildMerkleTree(); + sLog.Info(LOG_SERVER, "Hash: %s", Util::BinToASCII(block.merkleRootHash).c_str()); + + /*ByteBuffer buf(Util::ASCIIToBin("01000000010c432f4fb3e871a8bda638350b3d5c698cf431db8d6031b53e3fb5159e59d4a90000000000ffffffff0100f2052a010000001976a9143744841e13b90b4aca16fe793a7f88da3a23cc7188ac00000000")); Bitcoin::Transaction trans; buf >> trans; @@ -43,7 +66,7 @@ int Server::Run() ByteBuffer buf2; buf2 << trans; - sLog.Info(LOG_SERVER, "Trans: %s", Util::BinToASCII(buf2.vec).c_str()); + sLog.Info(LOG_SERVER, "Trans: %s", Util::BinToASCII(buf2.vec).c_str());*/ diff --git a/src/server/shared/Bitcoin/Block.h b/src/server/shared/Bitcoin/Block.h index ea332af..862e1c4 100644 --- a/src/server/shared/Bitcoin/Block.h +++ b/src/server/shared/Bitcoin/Block.h @@ -5,6 +5,9 @@ #include "Transaction.h" #include +#include + +#include "Log.h" namespace Bitcoin { @@ -22,12 +25,45 @@ namespace Bitcoin class Block : public BlockHeader { public: + // Serializable std::vector tx; - std::vector GenerateMerkle() + // Other data + std::vector > merkleTree; + + void BuildMerkleTree() { + merkleTree.clear(); + + uint64 branches = 1; + uint32 levels = 0; + while (branches < tx.size()) { + branches *= 2; + ++levels; + } + + // Add transactions + for (uint64 i = 0; i < branches; ++i) + merkleTree.push_back(tx[std::min(i, tx.size()-1)].GetHash()); + + uint32 merkleIndex = 0; + for (uint32 level = levels; level > 0; --level) + { + // Decrease before calculating because bottom level is transactions + branches /= 2; + + for (uint32 branch = 0; branch < branches; ++branch) + merkleTree.push_back(Crypto::SHA256D(Util::Join(merkleTree[merkleIndex++], merkleTree[merkleIndex++]))); + } + + // Last hash is merkle root + merkleRootHash = merkleTree[merkleTree.size()-1]; } }; + + // Block Serialization (Implementation in Serialization.cpp) + ByteBuffer& operator<<(ByteBuffer& a, Block& b); + ByteBuffer& operator>>(ByteBuffer& a, Block& b); } #endif diff --git a/src/server/shared/Bitcoin/Script.h b/src/server/shared/Bitcoin/Script.h index 17e8c75..859cbe2 100644 --- a/src/server/shared/Bitcoin/Script.h +++ b/src/server/shared/Bitcoin/Script.h @@ -63,6 +63,7 @@ namespace Bitcoin } }; + // Script Serialization (Implementation in Serialization.cpp) ByteBuffer& operator<<(ByteBuffer& a, Script& b); ByteBuffer& operator>>(ByteBuffer& a, Script& b); } diff --git a/src/server/shared/Bitcoin/Serialization.cpp b/src/server/shared/Bitcoin/Serialization.cpp index 440ba79..a8d5096 100644 --- a/src/server/shared/Bitcoin/Serialization.cpp +++ b/src/server/shared/Bitcoin/Serialization.cpp @@ -1,6 +1,7 @@ #include "VarInt.h" #include "Script.h" #include "Transaction.h" +#include "Block.h" using namespace Bitcoin; @@ -8,16 +9,16 @@ using namespace Bitcoin; ByteBuffer& Bitcoin::operator<<(ByteBuffer& a, VarInt& b) { if (b.value < 0xfd) { - a.Append(b.value, 1); + a.Append(b.value); } else if (b.value <= 0xffff) { - a.Append(0xfd, 1); - a.Append(b.value, 2); + a.Append(0xfd); + a.Append(b.value); } else if (b.value <= 0xffffffff) { - a.Append(0xfe, 1); - a.Append(b.value, 4); + a.Append(0xfe); + a.Append(b.value); } else { - a.Append(0xff, 1); - a.Append(b.value, 8); + a.Append(0xff); + a.Append(b.value); } return a; } @@ -61,7 +62,7 @@ ByteBuffer& Bitcoin::operator<<(ByteBuffer& a, OutPoint& b) ByteBuffer& Bitcoin::operator>>(ByteBuffer& a, OutPoint& b) { b.hash = a.ReadBytes(32); - b.n = a.Read(); + a >> b.n; return a; } @@ -77,7 +78,7 @@ ByteBuffer& Bitcoin::operator>>(ByteBuffer& a, TxIn& b) { a >> b.prevout; a >> b.script; - b.n = a.Read(); + a >> b.n; return a; } @@ -90,7 +91,7 @@ ByteBuffer& Bitcoin::operator<<(ByteBuffer& a, TxOut& b) } ByteBuffer& Bitcoin::operator>>(ByteBuffer& a, TxOut& b) { - b.value = a.Read(); + a >> b.value; a >> b.scriptPubKey; return a; } @@ -103,28 +104,29 @@ ByteBuffer& Bitcoin::operator<<(ByteBuffer& a, Transaction& b) // Inputs VarInt insize(b.in.size()); a << insize; - for (uint32 i = 0; i < b.in.size(); ++i) + for (uint64 i = 0; i < insize; ++i) a << b.in[i]; // Outputs VarInt outsize(b.out.size()); a << outsize; - for (uint32 i = 0; i < b.out.size(); ++i) + for (uint64 i = 0; i < outsize; ++i) a << b.out[i]; a << b.lockTime; + return a; } ByteBuffer& Bitcoin::operator>>(ByteBuffer& a, Transaction& b) { - b.version = a.Read(); + a >> b.version; // Inputs VarInt insize; a >> insize; b.in.resize(insize); - for (uint32 i = 0; i < insize; ++i) + for (uint64 i = 0; i < insize; ++i) a >> b.in[i]; // Outputs @@ -132,9 +134,47 @@ ByteBuffer& Bitcoin::operator>>(ByteBuffer& a, Transaction& b) a >> outsize; b.out.resize(outsize); - for (uint32 i = 0; i < outsize; ++i) + for (uint64 i = 0; i < outsize; ++i) a >> b.out[i]; - b.lockTime = a.Read(); + a >> b.lockTime; + + return a; +} + +// Block +ByteBuffer& Bitcoin::operator<<(ByteBuffer& a, Block& b) +{ + a << b.version; + a << b.prevBlockHash; + a << b.merkleRootHash; + a << b.time; + a << b.bits; + a << b.nonce; + + // Serialize transactions + VarInt txcount(b.tx.size()); + a << txcount; + for (uint64 i = 0; i < txcount; ++i) + a << b.tx[i]; + + return a; +} +ByteBuffer& Bitcoin::operator>>(ByteBuffer& a, Block& b) +{ + a >> b.version; + b.prevBlockHash = a.ReadBytes(32); + b.merkleRootHash = a.ReadBytes(32); + a >> b.time; + a >> b.bits; + a >> b.nonce; + + VarInt txcount; + a >> txcount; + + b.tx.resize(txcount); + for (uint64 i = 0; i < txcount; ++i) + a >> b.tx[i]; + return a; } diff --git a/src/server/shared/Bitcoin/Transaction.cpp b/src/server/shared/Bitcoin/Transaction.cpp new file mode 100644 index 0000000..7568798 --- /dev/null +++ b/src/server/shared/Bitcoin/Transaction.cpp @@ -0,0 +1,12 @@ +#include "Transaction.h" +#include "Util.h" + +namespace Bitcoin +{ + std::vector Transaction::GetHash() + { + ByteBuffer buf; + buf << *this; + return Crypto::SHA256D(buf.Bytes()); + } +} diff --git a/src/server/shared/Bitcoin/Transaction.h b/src/server/shared/Bitcoin/Transaction.h index 7a8e80c..1fe8014 100644 --- a/src/server/shared/Bitcoin/Transaction.h +++ b/src/server/shared/Bitcoin/Transaction.h @@ -5,6 +5,7 @@ #include "ByteBuffer.h" #include "VarInt.h" #include "Script.h" +#include "Crypto.h" namespace Bitcoin { @@ -49,6 +50,8 @@ namespace Bitcoin std::vector in; std::vector out; uint32 lockTime; + + std::vector GetHash(); }; // Transaction Serialization (Implementation in Serialization.cpp) diff --git a/src/server/shared/Bitcoin/VarInt.h b/src/server/shared/Bitcoin/VarInt.h index 801132e..5272247 100644 --- a/src/server/shared/Bitcoin/VarInt.h +++ b/src/server/shared/Bitcoin/VarInt.h @@ -18,6 +18,7 @@ namespace Bitcoin friend ByteBuffer& operator<<(ByteBuffer& a, VarInt& b); }; + // VarInt Serialization (Implementation in Serialization.cpp) ByteBuffer& operator<<(ByteBuffer& a, VarInt& b); ByteBuffer& operator>>(ByteBuffer& a, VarInt& b); } diff --git a/src/server/shared/ByteBuffer.h b/src/server/shared/ByteBuffer.h index 2bc7661..bec2094 100644 --- a/src/server/shared/ByteBuffer.h +++ b/src/server/shared/ByteBuffer.h @@ -20,50 +20,25 @@ public: Append(b); return *this; } - ByteBuffer& operator<<(uint8& b) - { - Append(b, 1); - return *this; - } - ByteBuffer& operator<<(uint16& b) - { - Append(b, 2); - return *this; - } - ByteBuffer& operator<<(uint32& b) - { - Append(b, 4); - return *this; - } - ByteBuffer& operator<<(uint64& b) - { - Append(b, 8); - return *this; - } - ByteBuffer& operator<<(int8& b) - { - Append(b, 1); - return *this; - } - ByteBuffer& operator<<(int16& b) - { - Append(b, 2); - return *this; - } - ByteBuffer& operator<<(int32& b) + + template + ByteBuffer& operator<<(T& b) { - Append(b, 4); + Append(b); return *this; } - ByteBuffer& operator<<(int64& b) + + template + ByteBuffer& operator>>(T& b) { - Append(b, 8); + b = Read(); return *this; } - void Append(uint64 data, size_t size) + template + void Append(T data) { - for (int i = 0; i < size; i++) + for (uint8 i = 0; i < sizeof(T); ++i) vec.push_back(data >> (i * 8)); } @@ -90,14 +65,19 @@ public: return NULL; T data = 0; - for (uint32 i = 0; i < size; ++i) - data += vec[pointer+i]<<(i*8); + for (uint64 i = 0; i < size; ++i) + data += (T)vec[pointer+i]<<(i*8); pointer += size; return data; } + std::vector Bytes() + { + return vec; + } + uint64 pointer; std::vector vec; }; diff --git a/src/server/shared/Crypto.cpp b/src/server/shared/Crypto.cpp new file mode 100644 index 0000000..52253eb --- /dev/null +++ b/src/server/shared/Crypto.cpp @@ -0,0 +1,25 @@ +#include "Crypto.h" + +namespace Crypto +{ + std::vector SHA256(std::vector data) + { + std::vector hash; + hash.resize(SHA256_DIGEST_LENGTH); + SHA256_CTX sha256; + SHA256_Init(&sha256); + SHA256_Update(&sha256, &data[0], data.size()); + SHA256_Final(&hash[0], &sha256); + return std::vector(hash.begin(), hash.end()); + } + + std::vector SHA256(std::string data) + { + return SHA256(std::vector(data.begin(), data.end())); + } + + std::vector SHA256D(std::vector data) + { + return SHA256(SHA256(data)); + } +} diff --git a/src/server/shared/Crypto.h b/src/server/shared/Crypto.h index 579a29b..55b4037 100644 --- a/src/server/shared/Crypto.h +++ b/src/server/shared/Crypto.h @@ -9,26 +9,9 @@ namespace Crypto { - std::vector SHA256(std::vector data) - { - std::vector hash; - hash.resize(SHA256_DIGEST_LENGTH); - SHA256_CTX sha256; - SHA256_Init(&sha256); - SHA256_Update(&sha256, &data[0], data.size()); - SHA256_Final(&hash[0], &sha256); - return std::vector(hash.begin(), hash.end()); - } - - std::vector SHA256(std::string data) - { - return SHA256(std::vector(data.begin(), data.end())); - } - - std::vector SHA256D(std::vector data) - { - return SHA256(SHA256(data)); - } + std::vector SHA256(std::vector data); + std::vector SHA256(std::string data); + std::vector SHA256D(std::vector data); } #endif diff --git a/src/server/shared/Util.cpp b/src/server/shared/Util.cpp index 167f915..ee71452 100644 --- a/src/server/shared/Util.cpp +++ b/src/server/shared/Util.cpp @@ -85,3 +85,10 @@ std::vector Util::Reverse(std::vector data) std::reverse(out.begin(), out.end()); return out; } + +std::vector Util::Join(std::vector v1, std::vector v2) +{ + std::vector v3 = v1; + v3.insert(v3.end(), v2.begin(), v2.end()); + return v3; +} diff --git a/src/server/shared/Util.h b/src/server/shared/Util.h index 9264aef..2163ad0 100644 --- a/src/server/shared/Util.h +++ b/src/server/shared/Util.h @@ -108,6 +108,7 @@ namespace Util std::vector ASCIIToBin(std::string str); std::string BinToASCII(std::vector data); std::vector Reverse(std::vector data); + std::vector Join(std::vector v1, std::vector v2); } #endif