Pages:
Author

Topic: Reading the block chain with a library? (Read 9730 times)

legendary
Activity: 980
Merit: 1008
October 07, 2012, 03:55:12 PM
#41
Never mind. I was structuring my code wrong so the previous cppWallet wasn't deleted from memory before starting with the next (I think that's what was wrong). This works:

Code:
from armoryengine import *


BDM_LoadBlockchainFile()
   
def get_balance(addresses):
   cppWallet = Cpp.BtcWallet()

   for address in addresses:
      cppWallet.addAddress_1_( address )

   TheBDM.registerWallet(cppWallet)
   TheBDM.scanBlockchainForTx(cppWallet)
   fullBalance = cppWallet.getFullBalance()
   balance = coin2str(fullBalance)
   TheBDM.unregisterWallet(cppWallet)

   return balance
legendary
Activity: 980
Merit: 1008
October 02, 2012, 05:14:36 PM
#40
How does one just query the balance of a Bitcoin address with armory? is there any calculations involved(like looping over tx history and sum up a balance) or can I just call it and print out a simple balance?

Im' sure a lot of programmers could benefit the solution to this question to write their own software to use armory for like making their own Blockchain.info website or w/e.

The code was in my example, but I guess my example was too long.  So here's an extraction of it.

Code:
from armoryengine import *

cppWallet = Cpp.BtcWallet()
cppWallet.addAddress_1_( addrStr_to_hash160('1EbAUHsitefy3rSECh8eK2fdAWTUbpVUDN') )   # addrStr
TheBDM.registerWallet(cppWallet)
BDM_LoadBlockchainFile()
TheBDM.scanBlockchainForTx(cppWallet)

fullBalance = cppWallet.getFullBalance()

print '\n\nBalance of this wallet:', coin2str(fullBalance)
etotheipi, say I want to avoid loading the blockchain file every time I want to use a Python program to find the balance of a bunch of addresses, what would be the appropriate way of doing this?

I have some code where I want to be able to query balances as quickly as possible, and would prefer not to wait while loading the now 3 GB block chain.

This way doesn't work for me. The first scan works fine, but the second scan hangs at TheBDM.scanBlockchainForTx(cppWallet).

Code:
from armoryengine import *

def init()
   BDM_LoadBlockchainFile()

def get_balance(addresses)
   cppWallet = Cpp.BtcWallet()

   for address in addresses:
      cppWallet.addAddress_1_( address )

   TheBDM.registerWallet(cppWallet)
   TheBDM.scanBlockchainForTx(cppWallet)
   fullBalance = cppWallet.getFullBalance()
   TheBDM.unregisterWallet(cppWallet)

   return fullBalance
Here's the gdb output from attaching to the python process.
Code:
(gdb) where
#0  0x00007f1728fc7980 in free@plt () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#1  0x00007f1729426f4a in BtcWallet::scanTx(Tx&, unsigned int, unsigned int, unsigned int) () from /home/rune/Programming/BitcoinArmory/_CppBlockUtils.so
#2  0x00007f172942ad3a in BlockDataManager_FileRefs::scanRegisteredTxForWallet(BtcWallet&, unsigned int, unsigned int) () from /home/rune/Programming/BitcoinArmory/_CppBlockUtils.so
#3  0x00007f172942b09d in BlockDataManager_FileRefs::scanBlockchainForTx(BtcWallet&, unsigned int, unsigned int) () from /home/rune/Programming/BitcoinArmory/_CppBlockUtils.so
#4  0x00007f172950cc12 in _wrap_BlockDataManager_FileRefs_scanBlockchainForTx () from /home/rune/Programming/BitcoinArmory/_CppBlockUtils.so
#5  0x000000000049c4d8 in PyEval_EvalFrameEx ()
#6  0x000000000049f1c0 in PyEval_EvalCodeEx ()
#7  0x00000000004983b8 in PyEval_EvalFrameEx ()
#8  0x000000000049f1c0 in PyEval_EvalCodeEx ()
#9  0x00000000004a9081 in PyRun_FileExFlags ()
#10 0x00000000004a9311 in PyRun_SimpleFileExFlags ()
#11 0x00000000004aa8bd in Py_Main ()
#12 0x00007f172a7a476d in __libc_start_main () from /lib/x86_64-linux-gnu/libc.so.6
#13 0x000000000041b9b1 in _start ()

So I guess I'd like to know:

  • What's the right way to make the library load the blockchain in advance, so it's always ready to process new addresses?
  • How do I properly make "TheBDM" forget the old addresses that were loaded via registerWallet? I'm just guessing unregisterWallet will do it, but I don't know. Is resetRegisteredWallets necessary as well?
legendary
Activity: 1428
Merit: 1093
Core Armory Developer
August 13, 2012, 09:53:41 PM
#39
For what it's worth I wrote some code in PHP that read the entire block-chain as downloaded from a "daily source" in tgz format early in development. I needed the block-chain and stats from it but didn't want to wrestle with APIs or wait for bitcoind to finish. Downloading the tgz is fast and pretty recent.

The binary format of blk0001.dat is well documented and you can parse the entire blockchain and validate it easily. My quad-core system under a highly limited VM can parse the entire block chain and validate the double SHA-256 hashes within about 10 seconds.

Hmm I haven't seen this "well documented" information quite yet would you mind posting a link so I can dive in?

The format is stupid simple:

Magic Bytes (4)
Num Block Bytes (4)
Header (80)
Num Tx in Block (VAR_INT)
Tx1
Tx2
...
TxN


legendary
Activity: 980
Merit: 1003
I'm not just any shaman, I'm a Sha256man
August 13, 2012, 09:33:44 PM
#38
For what it's worth I wrote some code in PHP that read the entire block-chain as downloaded from a "daily source" in tgz format early in development. I needed the block-chain and stats from it but didn't want to wrestle with APIs or wait for bitcoind to finish. Downloading the tgz is fast and pretty recent.

The binary format of blk0001.dat is well documented and you can parse the entire blockchain and validate it easily. My quad-core system under a highly limited VM can parse the entire block chain and validate the double SHA-256 hashes within about 10 seconds.

Hmm I haven't seen this "well documented" information quite yet would you mind posting a link so I can dive in?
member
Activity: 104
Merit: 11
August 13, 2012, 08:21:44 PM
#37
For what it's worth I wrote some code in PHP that read the entire block-chain as downloaded from a "daily source" in tgz format early in development. I needed the block-chain and stats from it but didn't want to wrestle with APIs or wait for bitcoind to finish. Downloading the tgz is fast and pretty recent.

The binary format of blk0001.dat is well documented and you can parse the entire blockchain and validate it easily. My quad-core system under a highly limited VM can parse the entire block chain and validate the double SHA-256 hashes within about 10 seconds.
legendary
Activity: 980
Merit: 1008
August 13, 2012, 03:00:36 PM
#36
Did it all from scratch, works perfectly now Smiley. Thanks!
legendary
Activity: 1428
Merit: 1093
Core Armory Developer
August 13, 2012, 12:43:26 PM
#35
^ If I 'make swig' from the BitcoinArmory root directory I get an error ("make: *** No rule to make target `swig'.  Stop."). If I enter the "cppForSwig" directory and 'make', I still get the error:


Make in the root directory should call "make swig" in the cppForSwig directory.  Or you can go into the cppForSwig directory and "make swig".  In both cases, it will recompile all the stuff and re-run swig to provide armoryengine.py access to the latest C++ utilities.  The error you are reporting is indicative of a version mismatch between the C++ and python code.

I recommend doing a fresh checkout, then go into the cppForSwig directory and type "make swig" (to be sure), and then try running it again.  If that doesn't work, then... ?
legendary
Activity: 980
Merit: 1008
August 13, 2012, 12:31:37 PM
#34
^ If I 'make swig' from the BitcoinArmory root directory I get an error ("make: *** No rule to make target `swig'.  Stop."). If I enter the "cppForSwig" directory and 'make', I still get the error:

Code:
rune@rune-desktop:~/Programming/BitcoinArmory/cppForSwig$ make
make BlockUtilsTest.out
make[1]: Entering directory `/home/rune/Programming/BitcoinArmory/cppForSwig'
make[1]: warning: jobserver unavailable: using -j1.  Add `+' to parent make rule.
g++  -c -O2 -pipe -fPIC  -Icryptopp -DUSE_CRYPTOPP -D__STDC_LIMIT_MACROS  UniversalTimer.cpp
g++  -c -O2 -pipe -fPIC  -Icryptopp -DUSE_CRYPTOPP -D__STDC_LIMIT_MACROS  BinaryData.cpp
g++  -c -O2 -pipe -fPIC  -Icryptopp -DUSE_CRYPTOPP -D__STDC_LIMIT_MACROS  FileDataPtr.cpp
g++  -c -O2 -pipe -fPIC  -Icryptopp -DUSE_CRYPTOPP -D__STDC_LIMIT_MACROS  BtcUtils.cpp
g++  -c -O2 -pipe -fPIC  -Icryptopp -DUSE_CRYPTOPP -D__STDC_LIMIT_MACROS  BlockObj.cpp
g++  -c -O2 -pipe -fPIC  -Icryptopp -DUSE_CRYPTOPP -D__STDC_LIMIT_MACROS  BlockUtils.cpp
g++  -c -O2 -pipe -fPIC  -Icryptopp -DUSE_CRYPTOPP -D__STDC_LIMIT_MACROS  EncryptionUtils.cpp
cd cryptopp; make libcryptopp.a; mv libcryptopp.a ..
make[2]: Entering directory `/home/rune/Programming/BitcoinArmory/cppForSwig/cryptopp'
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c 3way.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c adler32.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c algebra.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c algparam.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c arc4.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c asn.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c authenc.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c base32.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c base64.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c basecode.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c bfinit.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c blowfish.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c blumshub.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c camellia.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c cast.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c casts.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c cbcmac.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c ccm.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c channels.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c cmac.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c cpu.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c crc.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c cryptlib_bds.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c cryptlib.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c default.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c des.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c dessp.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c dh2.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c dh.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c dll.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c dsa.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c eax.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c ec2n.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c eccrypto.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c ecp.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c elgamal.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c emsa2.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c eprecomp.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c esign.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c files.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c filters.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c fips140.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c fipstest.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c gcm.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c gf2_32.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c gf256.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c gf2n.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c gfpcrypt.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c gost.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c gzip.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c hex.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c hmac.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c hrtimer.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c ida.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c idea.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c integer.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c iterhash.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c luc.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c md2.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c md4.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c md5.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c misc.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c modes.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c mqueue.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c mqv.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c nbtheory.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c network.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c oaep.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c osrng.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c pch.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c pkcspad.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c polynomi.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c pssr.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c pubkey.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c queue.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c rabin.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c randpool.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c rc2.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c rc5.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c rc6.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c rdtables.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c rijndael.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c ripemd.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c rng.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c rsa.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c rw.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c safer.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c salsa.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c seal.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c seed.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c serpent.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c shacal2.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c sha.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c sharkbox.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c shark.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c simple.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c skipjack.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c socketft.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c sosemanuk.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c square.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c squaretb.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c strciphr.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c tea.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c tftables.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c tiger.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c tigertab.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c trdlocal.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c ttmac.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c twofish.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c vmac.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c wait.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c wake.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c whrlpool.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c winpipes.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c xtr.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c xtrcrypt.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c zdeflate.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c zinflate.cpp
g++ -DNDEBUG -g -O2 -fPIC -mtune=generic -pipe -c zlib.cpp
ar -cr libcryptopp.a 3way.o adler32.o algebra.o algparam.o arc4.o asn.o authenc.o base32.o base64.o basecode.o bfinit.o blowfish.o blumshub.o camellia.o cast.o casts.o cbcmac.o ccm.o channels.o cmac.o cpu.o crc.o cryptlib_bds.o cryptlib.o default.o des.o dessp.o dh2.o dh.o dll.o dsa.o eax.o ec2n.o eccrypto.o ecp.o elgamal.o emsa2.o eprecomp.o esign.o files.o filters.o fips140.o fipstest.o gcm.o gf2_32.o gf256.o gf2n.o gfpcrypt.o gost.o gzip.o hex.o hmac.o hrtimer.o ida.o idea.o integer.o iterhash.o luc.o md2.o md4.o md5.o misc.o modes.o mqueue.o mqv.o nbtheory.o network.o oaep.o osrng.o pch.o pkcspad.o polynomi.o pssr.o pubkey.o queue.o rabin.o randpool.o rc2.o rc5.o rc6.o rdtables.o rijndael.o ripemd.o rng.o rsa.o rw.o safer.o salsa.o seal.o seed.o serpent.o shacal2.o sha.o sharkbox.o shark.o simple.o skipjack.o socketft.o sosemanuk.o square.o squaretb.o strciphr.o tea.o tftables.o tiger.o tigertab.o trdlocal.o ttmac.o twofish.o vmac.o wait.o wake.o whrlpool.o winpipes.o xtr.o xtrcrypt.o zdeflate.o zinflate.o zlib.o
ranlib libcryptopp.a
make[2]: Leaving directory `/home/rune/Programming/BitcoinArmory/cppForSwig/cryptopp'
g++  UniversalTimer.o BinaryData.o FileDataPtr.o BtcUtils.o BlockObj.o BlockUtils.o EncryptionUtils.o libcryptopp.a -o BlockUtilsTest.out -Icryptopp -DUSE_CRYPTOPP -D__STDC_LIMIT_MACROS  -lpthread  BlockUtilsTest.cpp
make[1]: Leaving directory `/home/rune/Programming/BitcoinArmory/cppForSwig'
rune@rune-desktop:~/Programming/BitcoinArmory/cppForSwig$ cd ..
rune@rune-desktop:~/Programming/BitcoinArmory$ ./armory-scan.py
********************************************************************************
Loading Armory Engine:
   Armory Version:       0.81
   PyBtcAddress Version: 1.00
   PyBtcWallet  Version: 1.35
Detected Operating system: Linux
   User home-directory   : /home/rune
   Satoshi BTC directory : /home/rune/.bitcoin/
   Armory home dir       : /home/rune/.armory/
Traceback (most recent call last):
  File "./armory-scan.py", line 12, in
    BDM_LoadBlockchainFile()
  File "/home/rune/Programming/BitcoinArmory/armoryengine.py", line 894, in BDM_LoadBlockchainFile
    return TheBDM.parseEntireBlockchain(blkdir)
  File "/home/rune/Programming/BitcoinArmory/CppBlockUtils.py", line 1115, in
  File "/home/rune/Programming/BitcoinArmory/CppBlockUtils.py", line 50, in _swig_getattr
AttributeError: parseEntireBlockchain
legendary
Activity: 1428
Merit: 1093
Core Armory Developer
August 06, 2012, 12:59:59 PM
#33
Any idea what this is about? bitcoin-qt is running and accepting connections over RPC.

EDIT: Running the newest version from git. On the master branch.

Did you "make swig" after pulling the 0.81 code?   A bunch of stuff changed under the hood with 0.80+, including the way that blockchain scanning is done.  This error looks like you're using the latest python code, but the underlying C++ utilities are still the 0.77-compiled versions.
legendary
Activity: 980
Merit: 1008
August 06, 2012, 12:47:34 PM
#32
How does one just query the balance of a Bitcoin address with armory? is there any calculations involved(like looping over tx history and sum up a balance) or can I just call it and print out a simple balance?

Im' sure a lot of programmers could benefit the solution to this question to write their own software to use armory for like making their own Blockchain.info website or w/e.

The code was in my example, but I guess my example was too long.  So here's an extraction of it.

Code:
from armoryengine import *

cppWallet = Cpp.BtcWallet()
cppWallet.addAddress_1_( addrStr_to_hash160('1EbAUHsitefy3rSECh8eK2fdAWTUbpVUDN') )   # addrStr
TheBDM.registerWallet(cppWallet)
BDM_LoadBlockchainFile()
TheBDM.scanBlockchainForTx(cppWallet)

fullBalance = cppWallet.getFullBalance()

print '\n\nBalance of this wallet:', coin2str(fullBalance)


I'm getting the following error when executing the above code:

Code:
rune@rune-desktop:~/Desktop$ /home/rune/Programming/BitcoinArmory/armory-scan.py
********************************************************************************
Loading Armory Engine:
   Armory Version:       0.81
   PyBtcAddress Version: 1.00
   PyBtcWallet  Version: 1.35
Detected Operating system: Linux
   User home-directory   : /home/rune
   Satoshi BTC directory : /home/rune/.bitcoin/
   Armory home dir       : /home/rune/.armory/
Traceback (most recent call last):
  File "/home/rune/Programming/BitcoinArmory/armory-scan.py", line 12, in
    BDM_LoadBlockchainFile()
  File "/home/rune/Programming/BitcoinArmory/armoryengine.py", line 894, in BDM_LoadBlockchainFile
    return TheBDM.parseEntireBlockchain(blkdir)
  File "/home/rune/Programming/BitcoinArmory/CppBlockUtils.py", line 1115, in
  File "/home/rune/Programming/BitcoinArmory/CppBlockUtils.py", line 50, in _swig_getattr
AttributeError: parseEntireBlockchain

Any idea what this is about? bitcoin-qt is running and accepting connections over RPC.

EDIT: Running the newest version from git. On the master branch.
legendary
Activity: 1526
Merit: 1134
You can also use bitcoinj for this kind of task, from either Java or C++. Take a look at the documentation here:

http://code.google.com/p/bitcoinj/
legendary
Activity: 1428
Merit: 1093
Core Armory Developer
I'm currently trying to write a program that connects multiple addresses to "entities". If there are 2 (or more) inputs used in a transaction, I assume that these belong to the same person. Atm all I want to do is to get a transaction and then get a list consisting of either ["Mined"] (if it was a coinbase) or the input address(es).

...

getSenderAddrIfAvailable() however seems not to catch a lot of input addresses, compared to your "count all addresses" that just counts the txouts I get only a fraction. I already read the comment

Code:
  // Not all TxIns have sendor info. Might have to go to the Outpoint and get
   // the corresponding TxOut to find the sender. In the case the sender is
   // not available, return false and don't write the output

but I'm kinda lost after calling txin.getOutPoint() - how do I then get to the OutTx object again and how do I know which of it's (possibly multiple) output addresses is the input address I'm looking for?

I wrote a special method in the BlockDataManager specifically for this situation (and I use it all the time).  It's because you can't always determine the identity behind a TxIn without actually retrieving the previous Tx that is being spent.  Thus, you need the help of the BlockDataManager, because a Tx object knows nothing about other transactions!

What you're looking for is this:

Code:
theTxIn = tx.getTxInRef(i)
senderAddr20 = TheBDM.getSenderAddr20(theTxIn)

Method "getSenderAddrIfAvailable()" does exactly what it says:  if it can deduce it from the TxIn, then it will return it.  However, coinbase TxIns do not have that info (though it could usually be deduced using some fancy math, but I never got around to implementing that).


legendary
Activity: 2618
Merit: 1007
This scanning is lower-level than what happens in Armory, so you are mainly using C++ objects.  You can find a full list of all the methods in BlockObjRef.h and BlockUtils.h.  Please ask questions if something isn't clear, or if you want to use some functionality not exemplified here.

I'm currently trying to write a program that connects multiple addresses to "entities". If there are 2 (or more) inputs used in a transaction, I assume that these belong to the same person. Atm all I want to do is to get a transaction and then get a list consisting of either ["Mined"] (if it was a coinbase) or the input address(es).

My code so far:
Code:
def getListOfInputAdresses(tx):
  allAddr = set()
  for nin in range(tx.getNumTxIn()):
    txin = tx.getTxInRef(nin)
    if txin.isCoinbase():
      return ["Mined"]
    else:
    if txin.getSenderAddrIfAvailable():
      parent = binary_to_hex(txin.getSenderAddrIfAvailable()) #<-- Hash160
      allAddr.add(parent)
  return list(allAddr)

getSenderAddrIfAvailable() however seems not to catch a lot of input addresses, compared to your "count all addresses" that just counts the txouts I get only a fraction. I already read the comment

Code:
   // Not all TxIns have sendor info. Might have to go to the Outpoint and get
   // the corresponding TxOut to find the sender. In the case the sender is
   // not available, return false and don't write the output

but I'm kinda lost after calling txin.getOutPoint() - how do I then get to the OutTx object again and how do I know which of it's (possibly multiple) output addresses is the input address I'm looking for?
legendary
Activity: 980
Merit: 1003
I'm not just any shaman, I'm a Sha256man
April 26, 2012, 07:49:32 PM
#28
I think that was rather related to my question about block timestamps... thanks by the way!
Still either way it helped me understand what those functions are used for and I'm still quite curious too. Apologies to any awkwardness felt from my responses.
legendary
Activity: 2618
Merit: 1007
April 26, 2012, 07:01:20 PM
#27
I think that was rather related to my question about block timestamps... thanks by the way!
legendary
Activity: 980
Merit: 1003
I'm not just any shaman, I'm a Sha256man
April 26, 2012, 06:49:54 PM
#26

$ ./bitcoind getblockhash 100000
000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506
$ ./bitcoind getblock 000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506
{
    "hash" : "000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506",
    "size" : 957,
    "height" : 100000,
    "version" : 1,
    "merkleroot" : "f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766",
    "time" : 1293623863,
    "nonce" : 274148111,
    "bits" : "1b04864c",
    "difficulty" : 14484.16236123,
    "tx" : [
        "8c14f0db3df150123e6f3dbbf30f8b955a8249b62ac1d1ff16284aefa3d06d87",
        "fff2525b8931402dd09222c50775608f75787bd2b87e56995a7bdd30f79702c4",
        "6359f0868171b1d194cbee1af2f16ea598ae8fad666d9b012c8ed2b79a236ec4",
        "e9a66845e05d5abc0ad04ec80f774a7e585c6e8db975962d069a522137b80c1d"
    ],
    "previousblockhash" : "000000000002d01c1fccc21636b607dfd930d31d01c3a62104612a1719011250",
    "nextblockhash" : "00000000000080b66c911bd5ba14a74260057311eaeb1982802f7010f1a9f090"
}


First call getblochash to find the hash of a block at a particular height, then use getblock to query information about the block with that given hash. The "time" field will tell you the block's timestamp (in seconds since epoch).
Ah that makes alot more sense. so im guessing with the array of tx data id have to query the tx info one by one to get the balances or transaction history? (maybe not transaction history but atleast an update for that parituclar block of the addresses involved)
legendary
Activity: 1072
Merit: 1181
April 26, 2012, 07:11:24 AM
#25

$ ./bitcoind getblockhash 100000
000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506
$ ./bitcoind getblock 000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506
{
    "hash" : "000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506",
    "size" : 957,
    "height" : 100000,
    "version" : 1,
    "merkleroot" : "f3e94742aca4b5ef85488dc37c06c3282295ffec960994b2c0d5ac2a25a95766",
    "time" : 1293623863,
    "nonce" : 274148111,
    "bits" : "1b04864c",
    "difficulty" : 14484.16236123,
    "tx" : [
        "8c14f0db3df150123e6f3dbbf30f8b955a8249b62ac1d1ff16284aefa3d06d87",
        "fff2525b8931402dd09222c50775608f75787bd2b87e56995a7bdd30f79702c4",
        "6359f0868171b1d194cbee1af2f16ea598ae8fad666d9b012c8ed2b79a236ec4",
        "e9a66845e05d5abc0ad04ec80f774a7e585c6e8db975962d069a522137b80c1d"
    ],
    "previousblockhash" : "000000000002d01c1fccc21636b607dfd930d31d01c3a62104612a1719011250",
    "nextblockhash" : "00000000000080b66c911bd5ba14a74260057311eaeb1982802f7010f1a9f090"
}


First call getblochash to find the hash of a block at a particular height, then use getblock to query information about the block with that given hash. The "time" field will tell you the block's timestamp (in seconds since epoch).
legendary
Activity: 980
Merit: 1003
I'm not just any shaman, I'm a Sha256man
April 25, 2012, 03:17:19 PM
#24
I tried the bitcoind getblockhash thing... I had no idea what information it was presenting me or how'd I utilize that information.

I ended up using Abe since it was best for my situation. Which was for me to be able to query things with PHP and MySql databases. At least myself and others have a thread to checkout later when they need some good bitcoin libraries.
legendary
Activity: 1428
Merit: 1093
Core Armory Developer
April 25, 2012, 11:40:06 AM
#23
I started the whole project because I wanted blockchain access from python.  I quickly found out that it just wasn't possible to scan the blockchain with python, at least if I wanted it to finish within an hour.  So the C++ layer does that and SWIG makes it possible to use it from python.  Unfortunately, SWIG has some quirks, such as difficulties with function overloading (hence the addAddress_1_() method instead of addAddress(), etc).  But, in general, it's been extraordinarily reliable.  Most of the C++ classes and structures are available from python as if they were native. 

That's why I recommended looking at BlockUtils.h and BlockObjRef.h, since that lists the all the functions available for most of the object types you will need.

Please let me know if there's more things you want to do with it, and I'll add more example code.    I had always wanted to setup some kind of tutorial for describing how to use armoryengine like this, but I never had a good excuse until now Smiley


P.S. - Pieter is right... a lot of the much simpler stuff could be done by just running bitcoind and scripting RPC calls to it.  But if you ever want to expand the functionality, I think a full library will be worth the time investment.
legendary
Activity: 980
Merit: 1003
I'm not just any shaman, I'm a Sha256man
April 24, 2012, 10:57:50 PM
#22
Oh yeah I noticed that part of your code, I just assumed that there was a quick way of going about this since it takes a few seconds to scan the block chain for one address and I'm looking for a way to scan and update the database for multiple addresses. Does that sound possible or am I stuck with this route you presented me? Thanks for your help btw I appreciate it.
Oh yeah I noticed that part of your code, I just assumed that there was a quick way of going about this since it takes a few seconds to scan the block chain for one address and I'm looking for a way to scan and update the database for multiple addresses. Does that sound possible or am I stuck with this route you presented me? Thanks for your help btw I appreciate it.

You can use as many addAddress_1_() calls as you want before a rescan, and the rescan will still take the same amount of time.  Load 20 addresses into your wallet before loading the blockchain, and it will take the same time as if you loaded in 10,000.

After the blockchain is loaded, if you add any new addresses to the wallet, the chain will be re-scanned on the "scanBlockchainForTx()" call, and again, it won't matter how many addresses that is, it'll take the same amount of time.
Thanks mate! that cleared things up.
Nice work btw
Pages:
Jump to: