Browse Source

Merkle tree hashing

peercoin
Intel 11 years ago
parent
commit
f2ec093448
  1. 27
      src/server/poolserver/Server/Server.cpp
  2. 38
      src/server/shared/Bitcoin/Block.h
  3. 1
      src/server/shared/Bitcoin/Script.h
  4. 72
      src/server/shared/Bitcoin/Serialization.cpp
  5. 12
      src/server/shared/Bitcoin/Transaction.cpp
  6. 3
      src/server/shared/Bitcoin/Transaction.h
  7. 1
      src/server/shared/Bitcoin/VarInt.h
  8. 56
      src/server/shared/ByteBuffer.h
  9. 25
      src/server/shared/Crypto.cpp
  10. 23
      src/server/shared/Crypto.h
  11. 7
      src/server/shared/Util.cpp
  12. 1
      src/server/shared/Util.h

27
src/server/poolserver/Server/Server.cpp

@ -34,8 +34,31 @@ int Server::Run() @@ -34,8 +34,31 @@ int Server::Run()
sLog.Info(LOG_SERVER, "Server is starting...");
//InitDatabase();
std::vector<byte> 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() @@ -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());*/

38
src/server/shared/Bitcoin/Block.h

@ -5,6 +5,9 @@ @@ -5,6 +5,9 @@
#include "Transaction.h"
#include <vector>
#include <algorithm>
#include "Log.h"
namespace Bitcoin
{
@ -22,12 +25,45 @@ namespace Bitcoin @@ -22,12 +25,45 @@ namespace Bitcoin
class Block : public BlockHeader
{
public:
// Serializable
std::vector<Transaction> tx;
std::vector<byte> GenerateMerkle()
// Other data
std::vector<std::vector<byte> > 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

1
src/server/shared/Bitcoin/Script.h

@ -63,6 +63,7 @@ namespace Bitcoin @@ -63,6 +63,7 @@ namespace Bitcoin
}
};
// Script Serialization (Implementation in Serialization.cpp)
ByteBuffer& operator<<(ByteBuffer& a, Script& b);
ByteBuffer& operator>>(ByteBuffer& a, Script& b);
}

72
src/server/shared/Bitcoin/Serialization.cpp

@ -1,6 +1,7 @@ @@ -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; @@ -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<uint8>(b.value);
} else if (b.value <= 0xffff) {
a.Append(0xfd, 1);
a.Append(b.value, 2);
a.Append<uint8>(0xfd);
a.Append<uint16>(b.value);
} else if (b.value <= 0xffffffff) {
a.Append(0xfe, 1);
a.Append(b.value, 4);
a.Append<uint8>(0xfe);
a.Append<uint32>(b.value);
} else {
a.Append(0xff, 1);
a.Append(b.value, 8);
a.Append<uint8>(0xff);
a.Append<uint64>(b.value);
}
return a;
}
@ -61,7 +62,7 @@ ByteBuffer& Bitcoin::operator<<(ByteBuffer& a, OutPoint& b) @@ -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<uint32>();
a >> b.n;
return a;
}
@ -77,7 +78,7 @@ ByteBuffer& Bitcoin::operator>>(ByteBuffer& a, TxIn& b) @@ -77,7 +78,7 @@ ByteBuffer& Bitcoin::operator>>(ByteBuffer& a, TxIn& b)
{
a >> b.prevout;
a >> b.script;
b.n = a.Read<uint32>();
a >> b.n;
return a;
}
@ -90,7 +91,7 @@ ByteBuffer& Bitcoin::operator<<(ByteBuffer& a, TxOut& b) @@ -90,7 +91,7 @@ ByteBuffer& Bitcoin::operator<<(ByteBuffer& a, TxOut& b)
}
ByteBuffer& Bitcoin::operator>>(ByteBuffer& a, TxOut& b)
{
b.value = a.Read<uint64>();
a >> b.value;
a >> b.scriptPubKey;
return a;
}
@ -103,28 +104,29 @@ ByteBuffer& Bitcoin::operator<<(ByteBuffer& a, Transaction& b) @@ -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<uint32>();
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) @@ -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<uint32>();
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;
}

12
src/server/shared/Bitcoin/Transaction.cpp

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
#include "Transaction.h"
#include "Util.h"
namespace Bitcoin
{
std::vector<byte> Transaction::GetHash()
{
ByteBuffer buf;
buf << *this;
return Crypto::SHA256D(buf.Bytes());
}
}

3
src/server/shared/Bitcoin/Transaction.h

@ -5,6 +5,7 @@ @@ -5,6 +5,7 @@
#include "ByteBuffer.h"
#include "VarInt.h"
#include "Script.h"
#include "Crypto.h"
namespace Bitcoin
{
@ -49,6 +50,8 @@ namespace Bitcoin @@ -49,6 +50,8 @@ namespace Bitcoin
std::vector<TxIn> in;
std::vector<TxOut> out;
uint32 lockTime;
std::vector<byte> GetHash();
};
// Transaction Serialization (Implementation in Serialization.cpp)

1
src/server/shared/Bitcoin/VarInt.h

@ -18,6 +18,7 @@ namespace Bitcoin @@ -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);
}

56
src/server/shared/ByteBuffer.h

@ -20,50 +20,25 @@ public: @@ -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<typename T>
ByteBuffer& operator<<(T& b)
{
Append(b, 4);
Append<T>(b);
return *this;
}
ByteBuffer& operator<<(int64& b)
template<typename T>
ByteBuffer& operator>>(T& b)
{
Append(b, 8);
b = Read<T>();
return *this;
}
void Append(uint64 data, size_t size)
template<typename T>
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: @@ -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<byte> Bytes()
{
return vec;
}
uint64 pointer;
std::vector<byte> vec;
};

25
src/server/shared/Crypto.cpp

@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
#include "Crypto.h"
namespace Crypto
{
std::vector<byte> SHA256(std::vector<byte> data)
{
std::vector<byte> 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<byte>(hash.begin(), hash.end());
}
std::vector<byte> SHA256(std::string data)
{
return SHA256(std::vector<byte>(data.begin(), data.end()));
}
std::vector<byte> SHA256D(std::vector<byte> data)
{
return SHA256(SHA256(data));
}
}

23
src/server/shared/Crypto.h

@ -9,26 +9,9 @@ @@ -9,26 +9,9 @@
namespace Crypto
{
std::vector<byte> SHA256(std::vector<byte> data)
{
std::vector<byte> 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<byte>(hash.begin(), hash.end());
}
std::vector<byte> SHA256(std::string data)
{
return SHA256(std::vector<byte>(data.begin(), data.end()));
}
std::vector<byte> SHA256D(std::vector<byte> data)
{
return SHA256(SHA256(data));
}
std::vector<byte> SHA256(std::vector<byte> data);
std::vector<byte> SHA256(std::string data);
std::vector<byte> SHA256D(std::vector<byte> data);
}
#endif

7
src/server/shared/Util.cpp

@ -85,3 +85,10 @@ std::vector<byte> Util::Reverse(std::vector<byte> data) @@ -85,3 +85,10 @@ std::vector<byte> Util::Reverse(std::vector<byte> data)
std::reverse(out.begin(), out.end());
return out;
}
std::vector<byte> Util::Join(std::vector<byte> v1, std::vector<byte> v2)
{
std::vector<byte> v3 = v1;
v3.insert(v3.end(), v2.begin(), v2.end());
return v3;
}

1
src/server/shared/Util.h

@ -108,6 +108,7 @@ namespace Util @@ -108,6 +108,7 @@ namespace Util
std::vector<byte> ASCIIToBin(std::string str);
std::string BinToASCII(std::vector<byte> data);
std::vector<byte> Reverse(std::vector<byte> data);
std::vector<byte> Join(std::vector<byte> v1, std::vector<byte> v2);
}
#endif

Loading…
Cancel
Save