5 * Created by Victor Grishchenko on 3/6/09.
6 * Copyright 2009 Delft Technical University. All rights reserved.
11 #include <openssl/sha.h>
21 const size_t Sha1Hash::SIZE = HASHSZ;
22 const Sha1Hash Sha1Hash::ZERO = Sha1Hash();
24 Sha1Hash::Sha1Hash(const Sha1Hash& left, const Sha1Hash& right) {
25 uint8_t data[HASHSZ*2];
26 memcpy(data,left.bits,SIZE);
27 memcpy(data+SIZE,right.bits,SIZE);
28 SHA1(data,SIZE*2,bits);
31 Sha1Hash::Sha1Hash(const uint8_t* data, size_t length) {
32 SHA1(data,length,bits);
35 Sha1Hash::Sha1Hash(const char* str) {
36 SHA1((const unsigned char*)str,strlen(str),bits);
39 Sha1Hash::Sha1Hash(bool hex, const char* hash) {
41 memcpy(bits,hash,SIZE);
44 string Sha1Hash::hex() const {
46 for(int i=0; i<HASHSZ; i++)
47 sprintf(hex+i*2, "%02x", bits[i]);
48 return string(hex,HASHSZ*2);
53 /*void HashTree::expand (bin tolen) {
55 munmap(bits,length*HASHSZ);
57 status.resize(length);
58 bits = (Sha1Hash*) mmap(NULL,length*HASHSZ,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
62 /*Sha1Hash HashTree::deriveRoot () {
63 int i = peaks.size()-1;
64 bin p = peaks[i].first;
65 Sha1Hash hash = peaks[i].second;
70 hash = Sha1Hash(hash,Sha1Hash::ZERO);
72 if (i<0 || peaks[i].first!=p.sibling())
73 return Sha1Hash::ZERO;
74 hash = Sha1Hash(peaks[i].second,hash);
82 HashTree::HashTree (int fd) {
83 //fd = open(filename,O_RDWR|O_CREAT,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
87 length = (st.st_size>>10) + (st.st_size%1024 ? 1 : 0);
88 mass = bin::lenpeak(length); // incorrect
90 status.resize(mass+1);
92 for(bin i=1; i<=mass; i++)
94 bits[i] = Sha1Hash(bits[i.left()],bits[i.right()]);
96 int len = pread(fd,buf,1024,i.offset()<<10);
97 bits[i] = Sha1Hash(buf,len);
100 bin::vec p = bin::peaks(length);
102 peaks.push_back(binhash(p.front(),bits[p.front()]));
108 HashTree::HashTree (const Sha1Hash& with_root) : root(with_root), length(0), mass(0) {
109 // recover the partially filled hash file
112 // works? then offer the rest
115 HashTree::~HashTree () {
119 HashTree::hashres_t HashTree::offerPeak (bin pos, Sha1Hash hash) {
120 if (bin(pos+1).layer())
124 peaks.push_back(binhash(pos,hash));
125 if (deriveRoot()==root) { // bingo
126 mass = peaks.back().first;
127 length = mass.length();
128 status.resize(mass+1);
130 for(int i=0; i<peaks.size(); i++) {
131 bits[peaks[i].first] = peaks[i].second;
132 status[peaks[i].first] = true;
136 return pos.layer() ? DUNNO : REJECT;
139 HashTree::hashres_t HashTree::offer (bin pos, const Sha1Hash& hash) {
140 if (!length) // only peak hashes are accepted at this point
141 return offerPeak(pos,hash);
145 return bits[pos]==hash ? ACCEPT : REJECT;
147 // walk to the nearest proven hash
148 if (bits[pos.sibling()]==Sha1Hash::ZERO)
150 bin p = pos.parent();
152 bits[p] = Sha1Hash(bits[p.left()],bits[p.right()]);
155 if ( bits[p] == Sha1Hash(bits[p.left()],bits[p.right()]) ) {
156 for(bin i=pos; i<p; i=i.parent())
157 status[i] = status[i.sibling()] = true;