Skip to content

Commit

Permalink
add methods to keep track of which snapshot claims have already been …
Browse files Browse the repository at this point in the history
…made
  • Loading branch information
sfultong committed Nov 10, 2015
1 parent eb3ed5c commit 1ca74f6
Show file tree
Hide file tree
Showing 7 changed files with 270 additions and 0 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ set(HEADER_FILES
)
set(SOURCE_FILES
${HEADER_FILES}
src/common.cpp
src/generate.cpp
src/claim.cpp
src/sqlite3.c
Expand Down
6 changes: 6 additions & 0 deletions include/bitcoin/bst/claim.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ namespace bst {
uint64_t getP2SHAmount(snapshot_reader& reader, const string& transaction, const string& address, const uint32_t input_index);
uint64_t getP2PKHBalance(snapshot_reader& reader, const vector<uint8_t>& vector);
uint64_t getP2SHBalance(snapshot_reader& reader, const vector<uint8_t>& vector);
bool hasP2PKH(snapshot_reader& reader, const vector<uint8_t>& vector);
bool hasP2SH(snapshot_reader& reader, const vector<uint8_t>& vector);
bool setP2PKHClaimed(snapshot_reader& reader, const vector<uint8_t>& vector);
bool setP2SHClaimed(snapshot_reader& reader, const vector<uint8_t>& vector);
bool getP2PKHClaimed(snapshot_reader& reader, const vector<uint8_t>& vector);
bool getP2SHClaimed(snapshot_reader& reader, const vector<uint8_t>& vector);
}

#endif
8 changes: 8 additions & 0 deletions include/bitcoin/bst/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,16 @@
#ifndef SPINOFF_TOOLKIT_COMMON_H
#define SPINOFF_TOOLKIT_COMMON_H

#include <cstddef>
#include <cstdint>
#include <vector>
#include <string>

using namespace std;

namespace bst {
static const string SNAPSHOT_NAME = "snapshot";
static const string SNAPSHOT_CLAIMED_NAME = "snapshot.claimed";

// std::array seems a problem, not sure why. Find out and switch these
typedef std::vector<uint8_t> uint160_t;
Expand All @@ -39,6 +45,8 @@ namespace bst {
snapshot_header() : version(0), block_hash(32), nP2PKH(0), nP2SH(0) { }
};
static const int HEADER_SIZE = 4 + 32 + 8 + 8;

void resetClaims(snapshot_header& header);
}

#endif
108 changes: 108 additions & 0 deletions src/claim.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,106 @@ namespace bst {
return 0;
}

int64_t getIndex(snapshot_reader &reader, const vector<uint8_t>& address, int64_t high, uint64_t base_offset)
{
int64_t low = 0;
while (low <= high) {
int64_t mid = (low + high) / 2;
uint64_t offset = base_offset + mid * 28;
reader.snapshot.seekg(offset);

vector<uint8_t> hashVec(20);
reader.snapshot.read(reinterpret_cast<char *>(&hashVec[0]), 20);

int comparison = compare(address, hashVec);
if (comparison == 0) {
return mid;
}
if (comparison < 0) {
high = mid - 1;
} else {
low = mid + 1;
}
}

// not found
return -1;
}

bool hasP2PKH(snapshot_reader& reader, const vector<uint8_t>& vector)
{
return -1 != getIndex(reader, vector, reader.header.nP2PKH, HEADER_SIZE);

}

bool hasP2SH(snapshot_reader& reader, const vector<uint8_t>& vector)
{
uint64_t base_offset = HEADER_SIZE + reader.header.nP2PKH * 28;
return -1 != getIndex(reader, vector, reader.header.nP2SH, base_offset);
}

bool setP2PKHClaimed(snapshot_reader& reader, const vector<uint8_t>& vector)
{
int64_t claimIndex = getIndex(reader, vector, reader.header.nP2PKH, HEADER_SIZE);
if (claimIndex == -1) return false;
fstream claimedFile(SNAPSHOT_CLAIMED_NAME, ios::in | ios::out | ios::binary);
claimedFile.seekg(claimIndex / 8, ios::beg);
char byte;
int bitSet = 1 << (claimIndex % 8);
claimedFile.read(&byte, 1);
byte |= bitSet;

claimedFile.seekg(claimIndex / 8, ios::beg);
claimedFile.write(&byte, 1);
claimedFile.close();
return true;
}

bool setP2SHClaimed(snapshot_reader& reader, const vector<uint8_t>& vector)
{
uint64_t base_offset = HEADER_SIZE + reader.header.nP2PKH * 28;
int64_t claimIndex = getIndex(reader, vector, reader.header.nP2SH, base_offset);
if (claimIndex == -1) return false;
fstream claimedFile(SNAPSHOT_CLAIMED_NAME, ios::in | ios::out | ios::binary);
int64_t bitOffset = reader.header.nP2PKH + claimIndex;
claimedFile.seekg(bitOffset / 8, ios::beg);
char byte;
int bitSet = 1 << (bitOffset % 8);
claimedFile.read(&byte, 1);
byte |= bitSet;

claimedFile.seekg((reader.header.nP2PKH + claimIndex) / 8, ios::beg);
claimedFile.write(&byte, 1);
claimedFile.close();
return true;
}

bool getP2PKHClaimed(snapshot_reader& reader, const vector<uint8_t>& vector)
{
int64_t claimIndex = getIndex(reader, vector, reader.header.nP2PKH, HEADER_SIZE);
ifstream claimedFile(SNAPSHOT_CLAIMED_NAME, ios::binary);
claimedFile.seekg(claimIndex / 8, ios::beg);
char byte;
int bitSet = 1 << (claimIndex % 8);
claimedFile.read(&byte, 1);
claimedFile.close();
return (byte & bitSet) != 0;
}

bool getP2SHClaimed(snapshot_reader& reader, const vector<uint8_t>& vector)
{
uint64_t base_offset = HEADER_SIZE + reader.header.nP2PKH * 28;
int64_t claimIndex = getIndex(reader, vector, reader.header.nP2SH, base_offset);
ifstream claimedFile(SNAPSHOT_CLAIMED_NAME, ios::binary);
int64_t bitOffset = reader.header.nP2PKH + claimIndex;
claimedFile.seekg(bitOffset / 8, ios::beg);
char byte;
int bitSet = 1 << (bitOffset % 8);
claimedFile.read(&byte, 1);
claimedFile.close();
return (byte & bitSet) != 0;
}

uint64_t getBalance(snapshot_reader &reader, const vector<uint8_t>& address, int64_t high, uint64_t base_offset)
{
int64_t low = 0;
Expand Down Expand Up @@ -127,6 +227,14 @@ namespace bst {
return 0;
}

// debug
/*
bc::short_hash sh;
copy(claimVector.begin(), claimVector.end(), sh.begin());
bc::payment_address address(111, sh);
cout << "recovered address " << address.encoded() << endl;
*/

return getBalance(reader, claimVector, reader.header.nP2PKH, HEADER_SIZE);
}

Expand Down
41 changes: 41 additions & 0 deletions src/common.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* Copyright (C) 2015 Bitcoin Spinoff Toolkit developers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "bitcoin/bst/common.h"
#include <bitcoin/bitcoin.hpp>

using namespace std;

namespace bst {

void resetClaims(snapshot_header& header)
{
uint64_t totalClaims = header.nP2PKH + header.nP2SH;
uint64_t bytesToWrite;
if (totalClaims % 8) {
bytesToWrite = totalClaims / 8 + 1;
} else {
bytesToWrite = totalClaims / 8;
}
ofstream claimedDatabase;
claimedDatabase.open(SNAPSHOT_CLAIMED_NAME, ios::binary);
char zeroByte = 0;
for (uint64_t i = 0; i < bytesToWrite; i++)
{
claimedDatabase.write(&zeroByte, 1);
}
claimedDatabase.close();
}
}
3 changes: 3 additions & 0 deletions src/generate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,9 @@ namespace bst {
snapshot.flush();
snapshot.close();

// write claim bitfield file
resetClaims(header);

return true;
}

Expand Down
103 changes: 103 additions & 0 deletions src/util/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,12 +290,115 @@ void test_validate_multisig()
cout << "result " << result << endl;
}

// not a test, just making a pretty base58 dummy address
void make_dummy_address()
{
// 1AsyXxD2CLwZtQEm7SuKcfEVpHuQVDQ174
string dummy = "1BitcoinSnapshotDummyAddress111111";
bc::data_chunk chunk = bc::decode_base58(dummy);
bc::short_hash sh = bc::short_hash();
copy(chunk.begin() + 1, chunk.begin() + 22, sh.begin());
bc::payment_address address(0, sh);
string recoveredAddress = address.encoded();
string hexString = bc::encode_base16(sh);
cout << recoveredAddress << endl;

cout << hexString << endl;
}

void test_claim_bitfield()
{
bst::snapshot_preparer preparer;
preparer.debug = false;
bst::prepareForUTXOs(preparer);
string pk1 = "1345FBB2B00E115C98C1D6E975C99B5431DE9CDE";
string pk2 = "2345FBB2B00E115C98C1D6E975C99B5431DE9CDE";
string pk3 = "3345FBB2B00E115C98C1D6E975C99B5431DE9CDE";
string pk4 = "4345FBB2B00E115C98C1D6E975C99B5431DE9CDE";
string pk5 = "5345FBB2B00E115C98C1D6E975C99B5431DE9CDE";
string pk6 = "6345FBB2B00E115C98C1D6E975C99B5431DE9CDE";
string pk7 = "7345FBB2B00E115C98C1D6E975C99B5431DE9CDE";
string pk8 = "8345FBB2B00E115C98C1D6E975C99B5431DE9CDE";
string pk9 = "9345FBB2B00E115C98C1D6E975C99B5431DE9CDE";
string pks[9] = { pk1, pk2, pk3, pk4, pk5, pk6, pk7, pk8, pk9 };
for (int i = 0; i < 9; i++) {
string transaction = "76A914" + pks[i] + "88AC";
vector<uint8_t> vector;
bst::decodeVector(transaction, vector);
bst::writeUTXO(preparer, vector, (uint64_t) i * 100);
}
string pk10 = "69a16fbc4929fc7c83ada40641411c09fe4b76d8";
string pk11 = "79a16fbc4929fc7c83ada40641411c09fe4b76d8";
string pkss[2] = { pk10, pk11 };
for (int i = 0; i < 2; i++) {
string transaction = "a914" + pkss[i] + "87";
vector<uint8_t> vector;
bst::decodeVector(transaction, vector);
bst::writeUTXO(preparer, vector, (uint64_t) 10000 * i);
}
vector<uint8_t> block_hash = vector<uint8_t>(32);
bst::writeJustSqlite(preparer);
bst::writeSnapshotFromSqlite(block_hash);


bst::snapshot_reader reader;
bst::openSnapshot(reader);

for (int i = 0; i < 9; i++) {
vector<uint8_t> vector;
bst::decodeVector(pks[i], vector);
if (getP2PKHClaimed(reader, vector)) {
cout << "after taking snapshot, claim " << i << " is set" << endl;
}
}
for (int i = 0; i < 2; i++) {
vector<uint8_t> vector;
bst::decodeVector(pkss[i], vector);
if (bst::getP2SHClaimed(reader, vector)) {
cout << "after taking snapshot, claim 1" << i << " is set" << endl;
}
if (! setP2SHClaimed(reader, vector)) {
cout << "error setting p2sh claim" << endl;
}
if (! getP2SHClaimed(reader, vector)) {
cout << "after setting, claim 10 is not set" << endl;
}
}

vector<uint8_t> vector, vector2;
for (int i = 0; i < 9; i++) {
vector.clear();
bst::decodeVector(pks[i], vector);
if (! bst::setP2PKHClaimed(reader, vector)) {
cout << "error setting p2pkh claim " << i << endl;
}
for (int j = 0; j < 9; j++) {
vector2.clear();
bst::decodeVector(pks[j], vector2);
if (j == i) {
if (! bst::getP2PKHClaimed(reader, vector2)) {
cout << "after setting, claim " << j << " is not set" << endl;
}
} else {
if (bst::getP2PKHClaimed(reader, vector2)) {
cout << "after setting " << i << " claim " << j << " is set" << endl;
}
}
}
bst::resetClaims(reader.header);
}

// cleanup
remove("temp.sqlite");
}

void test_all()
{
test_signing_check();
test_recover_signature();
test_store_and_claim();
test_write_sql_and_snapshot_separately();
test_claim_bitfield();
}

int main() {
Expand Down

0 comments on commit 1ca74f6

Please sign in to comment.