Skip to content

Commit

Permalink
Lots of changes:
Browse files Browse the repository at this point in the history
    . Heavily refactored code
    . Added some optimizations
    . Added a "taint" calculator callback
    . Output traditional bitcoin addresses for a fraction of allBalances
    . Added a method to convert bitcoin addresses to hash160 (not used yet)
  • Loading branch information
Znort 987 committed Jul 9, 2012
1 parent 1df1412 commit 20a0c0b
Show file tree
Hide file tree
Showing 12 changed files with 586 additions and 362 deletions.
8 changes: 8 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@ all:parser
@${CPLUS} -MD ${INC} ${COPT} -c cb/simpleStats.cpp -o .objs/simpleStats.o
@mv .objs/simpleStats.d .deps

.objs/taint.o : cb/taint.cpp
@echo c++ -- cb/taint.cpp
@mkdir -p .deps
@mkdir -p .objs
@${CPLUS} -MD ${INC} ${COPT} -c cb/taint.cpp -o .objs/taint.o
@mv .objs/taint.d .deps

.objs/transactions.o : cb/transactions.cpp
@echo c++ -- cb/transactions.cpp
@mkdir -p .deps
Expand Down Expand Up @@ -113,6 +120,7 @@ OBJS= \
.objs/allBalances.o \
.objs/closure.o \
.objs/simpleStats.o \
.objs/taint.o \
.objs/transactions.o \
.objs/callback.o \
.objs/opcodes.o \
Expand Down
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ blockparser

. Few dependencies: openssl-dev, boost

. Understand how the data structure underlying bitcoin works.

. Very quickly extract information from the entire blockchain.

. Code is simple and helps to understand how the data structure underlying bitcoin works.

Build it:
---------

Expand Down Expand Up @@ -54,6 +54,10 @@ blockparser

./parser allBalances >allBalances.txt

. See how much of the BTC 10K pizza tainted each of the TX in the chain

./parser taint >pizzaTaint.txt

Caveats:
--------

Expand Down Expand Up @@ -85,6 +89,7 @@ blockparser
. cb/closure.cpp : code to compute the transitive closure of an address.
. cb/allBalances.cpp : code to all balance of all addresses.
. cb/simpleStats.cpp : code to compute simple stats.
. cb/taint.cpp : code to compute the taint from a given TX to all TXs.
. cb/transactions.cpp : code to extract all transactions pertaining to an address.

. You can add your own custom callback. You can use the existing callbacks in
Expand All @@ -102,5 +107,5 @@ blockparser
License:
--------

Entire codebase is in the public domain.
Code is in the public domain.

32 changes: 14 additions & 18 deletions callback.cpp
Original file line number Diff line number Diff line change
@@ -1,30 +1,26 @@

#include <map>
#include <string>
#include <vector>
#include <string.h>
#include <callback.h>
static std::vector<Callback*> *callbacks;

typedef std::map<std::string, Callback*> Map;
static Map *map;

void Callback::add(
const char *name,
Callback *callback
)
Callback::Callback()
{
if(0==map)
map = new Map;

(*map)[std::string(name)] = callback;
if(0==callbacks) callbacks = new std::vector<Callback*>;
callbacks->push_back(this);
}

Callback *Callback::find(
const char *name
)
{
if(!map)
return 0;

auto i = map->find(std::string(name));
return (map->end()==i) ? 0 : i->second;
auto e = callbacks->end();
auto i = callbacks->begin();
while(i!=e) {
Callback *c = *(i++);
const char *n = c->name();
if(0==strcmp(name, n)) return c;
}
return 0;
}

49 changes: 26 additions & 23 deletions callback.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,26 @@
struct Block;
struct Callback
{
virtual bool needTXHash() = 0;
virtual int init(int argc, char *argv[]) = 0;

virtual void startMap(const uint8_t *p) = 0;
virtual void endMap(const uint8_t *p) = 0;
virtual void startBlock(const uint8_t *p) = 0;
virtual void endBlock(const uint8_t *p) = 0;

virtual void startTX(const uint8_t *p) = 0;
virtual void endTX(const uint8_t *p) = 0;
virtual void startInputs(const uint8_t *p) = 0;
virtual void endInputs(const uint8_t *p) = 0;
virtual void startInput(const uint8_t *p) = 0;
virtual void endInput(const uint8_t *p) = 0;
virtual void startOutputs(const uint8_t *p) = 0;
virtual void endOutputs(const uint8_t *p) = 0;
virtual void startOutput(const uint8_t *p) = 0;

virtual void startBlock( const Block *b) = 0;
virtual void endBlock( const Block *b) = 0;
Callback();
virtual const char *name() = 0;

virtual int init(int argc, char *argv[] ) { return 0; }
virtual bool needTXHash( ) { return false; }
virtual void startMap(const uint8_t *p ) { }
virtual void endMap(const uint8_t *p ) { }
virtual void startBlock(const uint8_t *p ) { }
virtual void endBlock(const uint8_t *p ) { }
virtual void startTX(const uint8_t *p, const uint8_t *hash) { }
virtual void endTX(const uint8_t *p ) { }
virtual void startInputs(const uint8_t *p ) { }
virtual void endInputs(const uint8_t *p ) { }
virtual void startInput(const uint8_t *p ) { }
virtual void endInput(const uint8_t *p ) { }
virtual void startOutputs(const uint8_t *p ) { }
virtual void endOutputs(const uint8_t *p ) { }
virtual void startOutput(const uint8_t *p ) { }
virtual void startBlock( const Block *b ) { }
virtual void endBlock( const Block *b ) { }

virtual void endOutput(
const uint8_t *p,
Expand All @@ -34,7 +34,9 @@
uint64_t outputIndex,
const uint8_t *outputScript,
uint64_t outputScriptSize
) = 0;
)
{
}

virtual void edge(
uint64_t value,
Expand All @@ -46,9 +48,10 @@
uint64_t inputIndex,
const uint8_t *inputScript,
uint64_t inputScriptSize
) = 0;
)
{
}

static void add(const char *name, Callback *callback);
static Callback *find(const char *name);
};

Expand Down
87 changes: 20 additions & 67 deletions cb/allBalances.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,50 +3,13 @@

#include <util.h>
#include <common.h>
#include <errlog.h>
#include <rmd160.h>
#include <callback.h>

#include <vector>
#include <string.h>

typedef const uint8_t *Hash160;
struct uint160_t { uint8_t v[kRIPEMD160ByteSize]; };

struct Hash160Hasher
{
uint64_t operator()(
const Hash160 &hash160
) const
{
uintptr_t i = reinterpret_cast<uintptr_t>(hash160);
const uint64_t *p = reinterpret_cast<const uint64_t*>(i);
return p[0];
}
};

struct Hash160Equal
{
bool operator()(
const Hash160 &ha,
const Hash160 &hb
) const
{
uintptr_t ia = reinterpret_cast<uintptr_t>(ha);
uintptr_t ib = reinterpret_cast<uintptr_t>(hb);

const uint64_t *a0 = reinterpret_cast<const uint64_t *>(ia);
const uint64_t *b0 = reinterpret_cast<const uint64_t *>(ib);
if(unlikely(a0[0]!=b0[0])) return false;
if(unlikely(a0[1]!=b0[1])) return false;

const uint32_t *a1 = reinterpret_cast<const uint32_t *>(ia);
const uint32_t *b1 = reinterpret_cast<const uint32_t *>(ib);
if(unlikely(a1[4]!=b1[4])) return false;

return true;
}
};

struct Addr
{
uint64_t sum;
Expand Down Expand Up @@ -106,20 +69,19 @@ struct AllBalances:public Callback
const uint8_t *script,
uint64_t scriptSize,
const uint8_t *txHash,
uint64_t value,
bool add,
int64_t value,
const uint8_t *downTXHash = 0
)
{
uint8_t addrType[3];
uint160_t pubKeyHash;
int type = solveOutputScript(pubKeyHash.v, script, scriptSize, addrType);
if(type<0)
if(unlikely(type<0))
return;

Addr *addr;
auto i = gAddrMap.find(pubKeyHash.v);
if(gAddrMap.end()!=i)
if(unlikely(gAddrMap.end()!=i))
addr = i->second;
else {
addr = allocAddr();
Expand All @@ -130,11 +92,10 @@ struct AllBalances:public Callback
gAllAddrs.push_back(addr);
}

if(add) addr->sum += value;
else addr->sum -= value;
addr->sum += value;

static uint64_t cnt = 0;
if(0==((cnt++)&0xFFFFF)) {
if(unlikely(0==((cnt++)&0xFFFFF))) {

double progress = (script-gFirstBlock)/(double)(gLastBlock-gFirstBlock);
printf(
Expand Down Expand Up @@ -162,8 +123,7 @@ struct AllBalances:public Callback
outputScript,
outputScriptSize,
txHash,
value,
true
value
);
}

Expand All @@ -183,8 +143,7 @@ struct AllBalances:public Callback
outputScript,
outputScriptSize,
upTXHash,
value,
false,
-(int64_t)value,
downTXHash
);
}
Expand All @@ -200,33 +159,27 @@ struct AllBalances:public Callback
auto s = gAllAddrs.begin();
std::sort(s, e, compare);

while(s<e) {
uint64_t i = 0;
uint64_t n = gAllAddrs.size() - 5000;
while(likely(s<e)) {
Addr *addr = *(s++);
printf("%24.8f ", (1e-8)*addr->sum);
showHex(addr->hash.v, kRIPEMD160ByteSize, false);

if(n<i) {
uint8_t buf[64];
hash160ToAddr(buf, addr->hash.v);
printf(" %s", buf);
}
printf("\n");
++i;
}
}


AllBalances()
virtual const char *name()
{
Callback::add("allBalances", this);
return "allBalances";
}

virtual void startBlock(const uint8_t *p) { }
virtual void endBlock(const uint8_t *p) { gLastBlock = p; }
virtual void startTX(const uint8_t *p) { }
virtual void endTX(const uint8_t *p) { }
virtual void startInputs(const uint8_t *p) { }
virtual void endInputs(const uint8_t *p) { }
virtual void startInput(const uint8_t *p) { }
virtual void endInput(const uint8_t *p) { }
virtual void startOutputs(const uint8_t *p) { }
virtual void endOutputs(const uint8_t *p) { }
virtual void startOutput(const uint8_t *p) { }
virtual void startBlock( const Block *b) { }
virtual void endBlock( const Block *b) { }
};

static AllBalances allBalances;
Expand Down
Loading

0 comments on commit 20a0c0b

Please sign in to comment.