PPCoin: Remove Gavin's bitcointools
authorSunny King <sunnyking9999@gmail.com>
Thu, 9 Aug 2012 22:47:45 +0000 (23:47 +0100)
committerSunny King <sunnyking9999@gmail.com>
Thu, 9 Aug 2012 22:47:45 +0000 (23:47 +0100)
21 files changed:
bitcointools/.gitignore [deleted file]
bitcointools/BCDataStream.py [deleted file]
bitcointools/LICENSE.txt [deleted file]
bitcointools/NOTES.txt [deleted file]
bitcointools/README.txt [deleted file]
bitcointools/__init__.py [deleted file]
bitcointools/address.py [deleted file]
bitcointools/base58.py [deleted file]
bitcointools/blkindex.py [deleted file]
bitcointools/block.py [deleted file]
bitcointools/blocks.py [deleted file]
bitcointools/dbdump.py [deleted file]
bitcointools/deserialize.py [deleted file]
bitcointools/enumeration.py [deleted file]
bitcointools/fixwallet.py [deleted file]
bitcointools/jsonToCSV.py [deleted file]
bitcointools/statistics.py [deleted file]
bitcointools/testBCDataStream.py [deleted file]
bitcointools/transaction.py [deleted file]
bitcointools/util.py [deleted file]
bitcointools/wallet.py [deleted file]

diff --git a/bitcointools/.gitignore b/bitcointools/.gitignore
deleted file mode 100644 (file)
index 0d20b64..0000000
+++ /dev/null
@@ -1 +0,0 @@
-*.pyc
diff --git a/bitcointools/BCDataStream.py b/bitcointools/BCDataStream.py
deleted file mode 100644 (file)
index cb2d1d0..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-#
-# Workalike python implementation of Bitcoin's CDataStream class.
-#
-import struct
-import StringIO
-import mmap
-
-class SerializationError(Exception):
-  """ Thrown when there's a problem deserializing or serializing """
-
-class BCDataStream(object):
-  def __init__(self):
-    self.input = None
-    self.read_cursor = 0
-
-  def clear(self):
-    self.input = None
-    self.read_cursor = 0
-
-  def write(self, bytes):  # Initialize with string of bytes
-    if self.input is None:
-      self.input = bytes
-    else:
-      self.input += bytes
-
-  def map_file(self, file, start):  # Initialize with bytes from file
-    self.input = mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_READ)
-    self.read_cursor = start
-  def seek_file(self, position):
-    self.read_cursor = position
-  def close_file(self):
-    self.input.close()
-
-  def read_string(self):
-    # Strings are encoded depending on length:
-    # 0 to 252 :  1-byte-length followed by bytes (if any)
-    # 253 to 65,535 : byte'253' 2-byte-length followed by bytes
-    # 65,536 to 4,294,967,295 : byte '254' 4-byte-length followed by bytes
-    # ... and the Bitcoin client is coded to understand:
-    # greater than 4,294,967,295 : byte '255' 8-byte-length followed by bytes of string
-    # ... but I don't think it actually handles any strings that big.
-    if self.input is None:
-      raise SerializationError("call write(bytes) before trying to deserialize")
-
-    try:
-      length = self.read_compact_size()
-    except IndexError:
-      raise SerializationError("attempt to read past end of buffer")
-
-    return self.read_bytes(length)
-
-  def write_string(self, string):
-    # Length-encoded as with read-string
-    self.write_compact_size(len(string))
-    self.write(string)
-
-  def read_bytes(self, length):
-    try:
-      result = self.input[self.read_cursor:self.read_cursor+length]
-      self.read_cursor += length
-      return result
-    except IndexError:
-      raise SerializationError("attempt to read past end of buffer")
-
-    return ''
-
-  def read_boolean(self): return self.read_bytes(1)[0] != chr(0)
-  def read_int16(self): return self._read_num('<h')
-  def read_uint16(self): return self._read_num('<H')
-  def read_int32(self): return self._read_num('<i')
-  def read_uint32(self): return self._read_num('<I')
-  def read_int64(self): return self._read_num('<q')
-  def read_uint64(self): return self._read_num('<Q')
-
-  def write_boolean(self, val): return self.write(chr(1) if val else chr(0))
-  def write_int16(self, val): return self._write_num('<h', val)
-  def write_uint16(self, val): return self._write_num('<H', val)
-  def write_int32(self, val): return self._write_num('<i', val)
-  def write_uint32(self, val): return self._write_num('<I', val)
-  def write_int64(self, val): return self._write_num('<q', val)
-  def write_uint64(self, val): return self._write_num('<Q', val)
-
-  def read_compact_size(self):
-    size = ord(self.input[self.read_cursor])
-    self.read_cursor += 1
-    if size == 253:
-      size = self._read_num('<H')
-    elif size == 254:
-      size = self._read_num('<I')
-    elif size == 255:
-      size = self._read_num('<Q')
-    return size
-
-  def write_compact_size(self, size):
-    if size < 0:
-      raise SerializationError("attempt to write size < 0")
-    elif size < 253:
-       self.write(chr(size))
-    elif size < 2**16:
-      self.write('\xfd')
-      self._write_num('<H', size)
-    elif size < 2**32:
-      self.write('\xfe')
-      self._write_num('<I', size)
-    elif size < 2**64:
-      self.write('\xff')
-      self._write_num('<Q', size)
-
-  def _read_num(self, format):
-    (i,) = struct.unpack_from(format, self.input, self.read_cursor)
-    self.read_cursor += struct.calcsize(format)
-    return i
-
-  def _write_num(self, format, num):
-    s = struct.pack(format, num)
-    self.write(s)
diff --git a/bitcointools/LICENSE.txt b/bitcointools/LICENSE.txt
deleted file mode 100644 (file)
index 31b5b47..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright (c) 2010 Gavin Andresen
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
diff --git a/bitcointools/NOTES.txt b/bitcointools/NOTES.txt
deleted file mode 100644 (file)
index 2531c93..0000000
+++ /dev/null
@@ -1,367 +0,0 @@
-Most of this information is now at the Protocol Specification page at the bitcoin wiki:
-  https://en.bitcoin.it/wiki/Protocol_specification
-
-One of these days I might check this document against the wiki, add any missing information to the wiki, and remove the information below.
-
-
-Transaction dissection notes:
------------------------------
-
-My first two transactions look like this:
-
-==WalletTransaction== f240...2582
-Merkle hashBlock: 6d40...0000
-1 tx in, 1 out
-['TxIn: prev(e9d4...d2f4:0) pubkey: 1Lfic7L3z7xUbxRDvMNFiE3QxKRmSSrvEH sig: 72:3045...1a01 65:0403...7b86']
-['TxOut: value: 500.00 pubkey: 19vcWM6EEbQHVdN2W8NXv9ySgsPjbZ6gU3 Script: DUP HASH160 20:61e4...614c EQUALVERIFY CHECKSIG']
- timeReceived:Thu May 27 14:25:48 2010 fromMe:True spent:True
-
-==WalletTransaction== f961...4472
-Merkle hashBlock: 7707...0000
-1 tx in, 2 out
-['TxIn: prev(f240...2582:0) pubkey: 19vcWM6EEbQHVdN2W8NXv9ySgsPjbZ6gU3 sig: 72:3045...a801 65:04a6...a541']
-['TxOut: value: 142.40 pubkey: 15F9miF9egehbeCiPKVSJSwgw5J96my7Rf Script: DUP HASH160 20:2e8d...5179 EQUALVERIFY CHECKSIG', 'TxOut: value: 357.60 pubkey: 1Av6tJSFv3bZvUfaALm4TQZmYvdeuHcbUb Script: DUP HASH160 20:6cc4...1755 EQUALVERIFY CHECKSIG']
- timeReceived:Fri May 28 13:55:23 2010 fromMe:True spent:True
-
-So: whoever has sending bc address 1Lfic7L3z7xUbxRDvMNFiE3QxKRmSSrvEH sent 500 bitcoins to
-my 19vcWM6EEbQHVdN2W8NXv9ySgsPjbZ6gU3 receiving address.
-
-I then sent 142.40 to bcaddress 15F9miF9egehbeCiPKVSJSwgw5J96my7Rf.
-And got 357.60 in change (Bitcoin created a new address for the change:  1Av6tJSFv3bZvUfaALm4TQZmYvdeuHcbUb)
-
-Spending generated coins looks different:
-
-Transaction 6403...cc0e
-['TxIn: COIN GENERATED coinbase:0464ba0e1c010a']
-['TxOut: value: 50.00 pubkey: 1Cpr8WJYa5igdo8AtPS24hfVLkk6ANZSWN Script: 65:0442...11c2 CHECKSIG']
-
-Transaction db39...8dcd:
-['TxIn: COIN GENERATED coinbase:0464ba0e1c0130']
-['TxOut: value: 50.00 pubkey: 1LuamEE1rL1QAdgn48gGFD9T9mnqSeP17w Script: 65:04f2...e10f CHECKSIG']
-
-==WalletTransaction== 3860...f888
-['TxIn: prev(6403...cc0e:0) pubkey: (None) sig: 72:3045...f501', 'TxIn: prev(db39...8dcd:0) pubkey: (None) sig: 73:3046...9\
-601']
-['TxOut: value: 100.00 pubkey: 1BBWNxMqU2bTwSVeUDVKmNYJrWr4D1pBrf Script: DUP HASH160 20:6fad...ab90 EQUALVERIFY CHECKSIG']
-
-Here I received 100 bitcoins from two 50 COIN GENERATED transactions.
-
-
-blkindex.dat serialization notes:
----------------------------------
-
-Keys beging with a serialized string, rest of key and value depend on that first string.  Possibilities are:
-
-tx : key continues with uint256 transaction hash/id (32 bytes)
- value is:
-  version : 32-bit unsigned int
-  CDiskTxPos : location of transaction (in the blk000N.dat files)
-  vector<CDiskTxPos> : location of transactions that spend this transaction's inputs
-
-blockindex : key continues with uint256 block hash (32 bytes)
- value is serialized CDiskBlockIndex
-
-version : value is integer version number
-
-hashBestChain : value is 32-byte SHA256 hash of last block in the longest block chain.
-
-
-wallet.dat serialization notes:
--------------------------------
-Berkely DB BTREE file (key-value pairs).
-
-Keys begin with a serialized string, rest of key and value depend on that first string.  Possibilities are:
-
-name : key continues with 34-character Bitcoin "hash160" address
- value is a simple string.
-
-tx : key continues with uint256 (32 bytes)
-  value is a serialized CTransaction+CMerkleTx+CWalletTx  (see below for details)
-
-key : key continues with vector<unsigned char> that is public key
-  value is vector<unsigned char> that is private key (full 271-byte
-    OpenSSL representation)
-
-wkey : key continues with vector<unsigned char> that is public key
-  value is serialized CWalletKey:
-    vector<unsigned char> that is private key
-    int64 nTimeCreated
-    int64 nTimeExpires
-    string comment
-
-ckey : enCrypted key continues with vector<unsigned char> that is public key
-  value is vector<unsigned char> that is private key (32 byte private part,
-    not full 271-byte OpenSSL representation)
-
-mkey : master key continues with unsigned int that is ID of the master key
-  value is serialized CMasterKey:
-    vector<unsigned char> encrypted key
-    vector<unsigned char> encrypted salt
-    unsigned int indicating the method to derive key from password
-    unsigned int indicating the number of times the derivation algorithm should be iterated
-    vector<unsigned char> holding other parameters to the derivation algorithm
-
-defaultkey :
-  value is vector<unsigned char> default key
-
-version :
-  value is int version number
-
-setting : key continues with setting name, value depends on setting as follows:
-  addrIncoming : CAddress serialized
-  addrProxy : CAddress serialized
-  fGenerateBitcoins : 1-character (boolean)
-  fLimitProcessors : 1-character (boolean)
-  fMinimizeOnClose : 1-character (boolean)
-  fMinimizeToTray : 1-character (boolean)
-  fUseProxy : 1-character (boolean)
-  nLimitProcessors : int
-  nTransactionFee : int64
-
-
-Complex value type serialization:
----------------------------------
-
-CDiskTxPos:
-  uint32 nFile       : Which of the blk000*.dat files
-  uint32 nBlockPos   : Byte position in file
-  uint32 nTxPos      : Byte position in file
-
-CDiskBlockIndex:
-  int nVersion
-  uint256 hashNext
-  uint32 nFile       : Which of the blk000*.dat files
-  uint32 nBlockPos   : Byte position in file
-  int nHeight        : height in block chain
-  int blockVersion   :  ??? Not sure why version is repeated...
-  uint256 hashPrev
-  uint256 hashMerkleRoot
-  uint32 nTime
-  uint32 nBits
-  uint32 nNonce
-
-CBlock:
-    # Note:   4 bytes: f9 be b4 d9  are written before records in blk000N.dat files
-    # But the nBlockPos pointers in CDiskBlockIndex points to start of serializedSize
-  int serializedSize
-  int version
-  uint256 hashPrev
-  uint256 hashMerkleRoot
-  uint32 nTime
-  uint32 nBits
-  uint32 nNonce
-  vector<CTransaction>
-
-CAddress:
-  int nVersion
-  unsigned int nTime
-  uint64 nServices
-  unsigned char[12] pchReserved
-  unsigned int ip
-  unsigned short port
-
-CTransaction:
-  int nVersion
-  vector<CTxIn> vin
-  vector<CTxOut> vout
-  unsigned int nLockTime
-
-CTxIn:
-  COutPoint prevout
-  CScript scriptSig
-  unsigned int nSequence
-
-CTxOut:
-  int64 nValue
-  CScript scriptPubKey
-
-COutPoint:
-  36 bytes(FLATDATA): 32-byte hash, 4-byte unsigned int
-
-CScript:
-  vector<unsigned char> containing built-in little scripting-language script
-   (opcodes and arguments to do crypto stuff)
-
-CMerkleTx:
-  ... serialize CTransaction, then:
-  uint256 hashBlock
-  vector<uint256> vMerkleBranch
-  int nIndex
-
-CWalletTx:
-  ... serialized CMerkleTx, then:
-  vector<CMerkleTx> vtxPrev
-  map<string,string> mapValue
-  vector<pair<string,string> > vOrderForm
-  unsigned int fTimeReceivedIsTxTime
-  unsigned int nTimeReceived
-  char fFromMe
-  char fSpent
-
-CInv:
-  int type   :   1:tx   2:block
-  uint256 hash
-
-CBlockLocator:
-  int nVersion
-  vector<uint256>    # Block hashes, newest back to genesis block (dense to start, but then sparse)
-
-string:
-  1/3/5/9 bytes giving length:
-    1 byte if length < 253.
-    otherwise byte value '253'+ushort, '254'+uint, '255'+uint64
-  then length bytes.
-
-vector<type>:
-  1/3/5/9 bytes giving count (see string, above)
-  followed by that many <types> serialized one-after-another
-
-pair:
-  just first item followed by second item
-
-
-PUBLIC KEYS TO BITCOIN ADDRESSES
---------------------------------
-
-Public key, in memory (65 bytes):
-
-0x94c7818:  0x04        0x57    0xcc    0xad    0xd7    0x1e    0xb0    0xf3
-0x94c7820:  0xc1        0x9d    0x22    0xb9    0xba    0x0e    0xa1    0xf3
-0x94c7828:  0x44        0x2a    0x6f    0x12    0x31    0x46    0xb5    0xbd
-0x94c7830:  0xff        0x10    0x60    0xbc    0xd1    0x11    0x68    0xe6
-0x94c7838:  0x6a        0x71    0xbe    0xd4    0xda    0x17    0x7c    0x12
-0x94c7840:  0xd7        0x30    0x9a    0xdd    0xfd    0xf5    0x6c    0x31
-0x94c7848:  0xd5        0xc8    0xa2    0x7b    0x8e    0x6a    0x22    0x20
-0x94c7850:  0x38        0x42    0xc6    0xc2    0x4f    0xd5    0x9b    0xd7
-0x94c7858:  0xb7
-Python string:
-public_key = "\x04\x57\xcc\xad\xd7\x1e\xb0\xf3\xc1\x9d\x22\xb9\xba\x0e\xa1\xf3\x44\x2a\x6f\x12\x31\x46\xb5\xbd\xff\x10\x60\xbc\xd1\x11\x68\xe6\x6a\x71\xbe\xd4\xda\x17\x7c\x12\xd7\x30\x9a\xdd\xfd\xf5\x6c\x31\xd5\xc8\xa2\x7b\x8e\x6a\x22\x20\x38\x42\xc6\xc2\x4f\xd5\x9b\xd7\xb7"
-
-SHA256 hash of that is:
-0xb6890938: 0x0d        0x72    0xab    0x02    0xc8    0xab    0x52    0xce
-0xb6890940: 0x7e        0x6b    0x04    0x00    0x95    0x58    0x09    0xf0
-0xb6890948: 0x93        0x48    0x21    0xb6    0x26    0xc3    0x27    0xc7
-0xb6890950: 0x9a        0x07    0x62    0xfd    0xbc    0x5e    0xb8    0xa5
-h1 = SHA256.new(public_key).digest()
-
-RIPEMD160(SHA256(public key)) is:
-0xb68909ac: 0x5c        0xc8    0x7f    0x4a    0x3f    0xdf    0xe3    0xa2
-0xb68909b4: 0x34        0x6b    0x69    0x53    0x26    0x7c    0xa8    0x67
-0xb68909bc: 0x28        0x26    0x30    0xd3
-h2 = RIPEMD160.new(h1).digest()
-
-Put version number '0x00' byte onto front:
-0x9eeb840:  0x00   0x5c   0xc8 0x7f 0x4a        0x3f    0xdf    0xe3
-0x9eeb848:  0xa2   0x34   0x6b 0x69 0x53        0x26    0x7c    0xa8
-0x9eeb850:  0x67   0x28   0x26 0x30 0xd3
-vh2 = "\x00"+h2
-
-Hash (double-SHA256) that:
-0xb68908e8:   0xf9   0xb7 0x8e  0x64    0x6e    0x20    0x27    0xc4
-0xb68908f0:   0xaa   0x62 0x66  0x04    0x2e    0xb6    0xa2    0xe0
-0xb68908f8:   0x41   0x03 0x9d  0xd8    0xe2    0x24    0x24    0xe8
-0xb6890900:   0x50   0xac 0x20  0x29    0xfb    0xcd    0xb4    0x6e
-h3=SHA256.new(SHA256.new(vh2).digest()).digest()
-
-Add first 4 bytes from Hash object onto end as check-bytes:
-0x9fa6628:  0x00  0x5c  0xc8    0x7f    0x4a    0x3f    0xdf    0xe3
-0x9fa6630:  0xa2  0x34  0x6b    0x69    0x53    0x26    0x7c    0xa8
-0x9fa6638:  0x67  0x28  0x26    0x30    0xd3    0xf9    0xb7    0x8e
-0x9fa6640:  0x64
-addr=vh2+h3[0:4]
-
-Result length should be:  int(math.floor(len(addr)*8/math.log(58,2)))
-Base58 encode that, front-pad with '1's if less than expected length
-to get:   19TbMSWwHvnxAKy12iNm3KdbGfzfaMFViT
-
-
-WIRE PROTOCOL NOTES
--------------------
-Default port is 8333
-
-// Message format                                                                                                       
-//  (4) message start    { 0xf9, 0xbe, 0xb4, 0xd9 }
-//  (12) command
-//  (4) size       -- number of bytes of data
-//  (4) checksum   -- First four bytes of double SHA256 hash of data
-//  (x) data
-
- --> messages might be split by network layer...
-
-Commands are:
-
-"version" :
-  int nVersion
-  uint64 nServices
-  int64 nTime
-  CAddress addrMe
-  CAddress addrFrom   # if nVersion > 106
-  uint64 nNonce
-  string strSubVer    # if nVersion > 106
-  int nStartingHeight # if nVersion > 209
-
-nNonce is random value (I think), used to detect self-connection.
-
-"verack" : no data.  Sent to sync min version (peer, peer)
-
-"addr" :
-  vector<CAddress>
-      (relayed to 10 random nodes so they spread)
-
-"inv" :
-  vector<CInv>
-
-"getdata" :   Asks for blocks or tx's (response is "block" or "tx" messages)
-  vector<CInv>
-
-"getblocks" :
-  CBLockLocator
-  uint256 hashStop
-
-"tx" :
-  CTransaction
-
-"block" :
-  CBlock
-
-"getaddr" : no data ("please send me addr messages")
-
-"checkorder"
-  uint256 hashReply
-  CWalletTx order
-
-"submitorder"
-  uint256 hashReply
-  CWalletTx wtxNew
-
-"reply"
-  uint256 hashReply
-
-"ping" : no data (and no reply)
-
-
-TRANSACTION SIGNING NOTES
--------------------------
-
-So, I want to spend some bitcoin.
-First, I gotta have a Transaction to me-- specifically, a Transaction with a TxOut that contains a scriptPubKey that I can satisfy.
-
-TxOut.scriptPubKey's come in a couple different flavors:
- DUP HASH160 {hash160(public_key) EQUALVERIFY CHECKSIG
-   --> I have to be able to supply a matching TxIn.scriptSig with: signature and public key
- (public key) CHECKSIG
-   --> I have to supply a matching TxIn.scriptSig with: signature
-
-TODO: figure out what, exactly, is hashed (and how), and how, exactly, that hash value is signed with the private key.
-
-DIFFICULTY, NBITS, BN_mpi2bn
-----------------------------
-
-Hash targets are stored as "compact bignums;" the production block chain has an initial target of:
-0x1d00ffff  ... which means "create a bignum that is 0x1d (29) bytes long and has 0x00ffff as the
-three bytes on the big end."  Or: 0xffff0000000000000000000000000000000000000000000000000000
-
-As I write this, the current block->nBits is 0x1c010c5.  To compute difficulty:
-  php -r '$nBits = 0x1c010c5a; print( (0xffff << ((0x1d-($nBits>>24))*8)) / ($nBits&0xffffff) );'
-
-
diff --git a/bitcointools/README.txt b/bitcointools/README.txt
deleted file mode 100644 (file)
index 0939cf3..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
------ dbdump.py -----
-Run    dbdump.py --help    for usage.  Database files are opened read-only, but
-you might want to backup your Bitcoin wallet.dat file just in case.
-
-You must quit Bitcoin before reading the transactions, blocks, or address database files.
-
-Requires the pycrypto library from  http://www.dlitz.net/software/pycrypto/
-to translate public keys into human-friendly Bitcoin addresses.
-
-Examples:
-
-Print out  wallet keys and transactions:
-  dbdump.py --wallet --wallet-tx
-
-Print out the "genesis block" (the very first block in the proof-of-work block chain):
-  dbdump.py --block=000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
-
-Print out one of the transactions from my wallet:
-  dbdump.py --transaction=c6e1bf883bceef0aa05113e189982055d9ba7212ddfc879798616a0d0828c98c
-  dbdump.py --transaction=c6e1...c98c
-
-Print out all 'received' transactions that aren't yet spent:
-  dbdump.py --wallet-tx-filter='fromMe:False.*spent:False'
-
-Print out all blocks involving transactions to the Bitcoin Faucet:
-  dbdump.py --search-blocks=15VjRaDX9zpbA8LVnbrCAFzrVzN7ixHNsC
-
-There's a special search term to look for non-standard transactions:
-  dbdump.py --search-blocks=NONSTANDARD_CSCRIPTS
-
------ statistics.py -----
-Scan all the transactions in the block chain and dump out a .csv file that shows transaction volume per month.
-
------ fixwallet.py -----
-Half-baked utility that reads a wallet.dat and writes out a new wallet.dat.
-
-Only half-baked because to be really useful I'd have to write serialize routines to re-pack data after modifying it...
-
------ jsonToCSV.py -----
-Read JSON list-of-objects from standard input, writes CSV file to standard output.
-Useful for converting bitcoind's listtransactions output to CSV that can be
-imported into a spreadsheet.
diff --git a/bitcointools/__init__.py b/bitcointools/__init__.py
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/bitcointools/address.py b/bitcointools/address.py
deleted file mode 100644 (file)
index 8fca690..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# Code for parsing the addr.dat file
-# NOTE: I think you have to shutdown the Bitcoin client to
-# successfully read addr.dat...
-#
-
-from bsddb.db import *
-import logging
-from operator import itemgetter
-import sys
-import time
-
-from BCDataStream import *
-from base58 import public_key_to_bc_address
-from util import short_hex
-from deserialize import *
-
-def dump_addresses(db_env):
-  db = DB(db_env)
-  try:
-    r = db.open("addr.dat", "main", DB_BTREE, DB_THREAD|DB_RDONLY)
-  except DBError:
-    r = True
-
-  if r is not None:
-    logging.error("Couldn't open addr.dat/main. Try quitting Bitcoin and running this again.")
-    sys.exit(1)
-
-  kds = BCDataStream()
-  vds = BCDataStream()
-
-  for (key, value) in db.items():
-    kds.clear(); kds.write(key)
-    vds.clear(); vds.write(value)
-
-    type = kds.read_string()
-
-    if type == "addr":
-      d = parse_CAddress(vds)
-      print(deserialize_CAddress(d))
-
-  db.close()
diff --git a/bitcointools/base58.py b/bitcointools/base58.py
deleted file mode 100644 (file)
index 0d034b8..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-#!/usr/bin/env python
-
-"""encode/decode base58 in the same way that Bitcoin does"""
-
-import math
-
-__b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
-__b58base = len(__b58chars)
-
-def b58encode(v):
-  """ encode v, which is a string of bytes, to base58.    
-  """
-
-  long_value = 0L
-  for (i, c) in enumerate(v[::-1]):
-    long_value += (256**i) * ord(c)
-
-  result = ''
-  while long_value >= __b58base:
-    div, mod = divmod(long_value, __b58base)
-    result = __b58chars[mod] + result
-    long_value = div
-  result = __b58chars[long_value] + result
-
-  # Bitcoin does a little leading-zero-compression:
-  # leading 0-bytes in the input become leading-1s
-  nPad = 0
-  for c in v:
-    if c == '\0': nPad += 1
-    else: break
-
-  return (__b58chars[0]*nPad) + result
-
-def b58decode(v, length):
-  """ decode v into a string of len bytes
-  """
-  long_value = 0L
-  for (i, c) in enumerate(v[::-1]):
-    long_value += __b58chars.find(c) * (__b58base**i)
-
-  result = ''
-  while long_value >= 256:
-    div, mod = divmod(long_value, 256)
-    result = chr(mod) + result
-    long_value = div
-  result = chr(long_value) + result
-
-  nPad = 0
-  for c in v:
-    if c == __b58chars[0]: nPad += 1
-    else: break
-
-  result = chr(0)*nPad + result
-  if length is not None and len(result) != length:
-    return None
-
-  return result
-
-try:
-  # Python Crypto library is at: http://www.dlitz.net/software/pycrypto/
-  # Needed for RIPEMD160 hash function, used to compute
-  # Bitcoin addresses from internal public keys.
-  import Crypto.Hash.SHA256 as SHA256
-  import Crypto.Hash.RIPEMD160 as RIPEMD160
-  have_crypto = True
-except ImportError:
-  have_crypto = False
-
-def hash_160(public_key):
-  if not have_crypto:
-    return ''
-  h1 = SHA256.new(public_key).digest()
-  h2 = RIPEMD160.new(h1).digest()
-  return h2
-
-def public_key_to_bc_address(public_key):
-  if not have_crypto:
-    return ''
-  h160 = hash_160(public_key)
-  return hash_160_to_bc_address(h160)
-
-def hash_160_to_bc_address(h160):
-  if not have_crypto:
-    return ''
-  vh160 = "\x00"+h160  # \x00 is version 0
-  h3=SHA256.new(SHA256.new(vh160).digest()).digest()
-  addr=vh160+h3[0:4]
-  return b58encode(addr)
-
-def bc_address_to_hash_160(addr):
-  bytes = b58decode(addr, 25)
-  return bytes[1:21]
-
-if __name__ == '__main__':
-    x = '005cc87f4a3fdfe3a2346b6953267ca867282630d3f9b78e64'.decode('hex_codec')
-    encoded = b58encode(x)
-    print encoded, '19TbMSWwHvnxAKy12iNm3KdbGfzfaMFViT'
-    print b58decode(encoded, len(x)).encode('hex_codec'), x.encode('hex_codec')
diff --git a/bitcointools/blkindex.py b/bitcointools/blkindex.py
deleted file mode 100644 (file)
index faf1113..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-#
-# Code for parsing the blkindex.dat file
-#
-
-from bsddb.db import *
-import logging
-from operator import itemgetter
-import sys
-import time
-
-from BCDataStream import *
-from base58 import public_key_to_bc_address
-from util import short_hex
-from deserialize import *
-
-def dump_blkindex_summary(db_env):
-  db = DB(db_env)
-  try:
-    r = db.open("blkindex.dat", "main", DB_BTREE, DB_THREAD|DB_RDONLY)
-  except DBError:
-    r = True
-
-  if r is not None:
-    logging.error("Couldn't open blkindex.dat/main.  Try quitting any running Bitcoin apps.")
-    sys.exit(1)
-
-  kds = BCDataStream()
-  vds = BCDataStream()
-
-  n_tx = 0
-  n_blockindex = 0
-
-  print("blkindex file summary:")
-  for (key, value) in db.items():
-    kds.clear(); kds.write(key)
-    vds.clear(); vds.write(value)
-
-    type = kds.read_string()
-
-    if type == "tx":
-      n_tx += 1
-    elif type == "blockindex":
-      n_blockindex += 1
-    elif type == "version":
-      version = vds.read_int32()
-      print(" Version: %d"%(version,))
-    elif type == "hashBestChain":
-      hash = vds.read_bytes(32)
-      print(" HashBestChain: %s"%(hash.encode('hex_codec'),))
-    else:
-      logging.warn("blkindex: unknown type '%s'"%(type,))
-      continue
-
-  print(" %d transactions, %d blocks."%(n_tx, n_blockindex))
-  db.close()
diff --git a/bitcointools/block.py b/bitcointools/block.py
deleted file mode 100644 (file)
index bff0744..0000000
+++ /dev/null
@@ -1,240 +0,0 @@
-#
-# Code for dumping a single block, given its ID (hash)
-#
-
-from bsddb.db import *
-import logging
-import os.path
-import re
-import sys
-import time
-
-from BCDataStream import *
-from base58 import public_key_to_bc_address
-from util import short_hex, long_hex
-from deserialize import *
-
-def _open_blkindex(db_env):
-  db = DB(db_env)
-  try:
-    r = db.open("blkindex.dat", "main", DB_BTREE, DB_THREAD|DB_RDONLY)
-  except DBError:
-    r = True
-  if r is not None:
-    logging.error("Couldn't open blkindex.dat/main.  Try quitting any running Bitcoin apps.")
-    sys.exit(1)
-  return db
-
-def _read_CDiskTxPos(stream):
-  n_file = stream.read_uint32()
-  n_block_pos = stream.read_uint32()
-  n_tx_pos = stream.read_uint32()
-  return (n_file, n_block_pos, n_tx_pos)
-
-def _dump_block(datadir, nFile, nBlockPos, hash256, hashNext, do_print=True):
-  blockfile = open(os.path.join(datadir, "blk%04d.dat"%(nFile,)), "rb")
-  ds = BCDataStream()
-  ds.map_file(blockfile, nBlockPos)
-  d = parse_Block(ds)
-  block_string = deserialize_Block(d)
-  ds.close_file()
-  blockfile.close()
-  if do_print:
-    print "BLOCK "+long_hex(hash256[::-1])
-    print "Next block: "+long_hex(hashNext[::-1])
-    print block_string
-  return block_string
-
-def _parse_block_index(vds):
-  d = {}
-  d['version'] = vds.read_int32()
-  d['hashNext'] = vds.read_bytes(32)
-  d['nFile'] = vds.read_uint32()
-  d['nBlockPos'] = vds.read_uint32()
-  d['nHeight'] = vds.read_int32()
-
-  header_start = vds.read_cursor
-  d['b_version'] = vds.read_int32()
-  d['hashPrev'] = vds.read_bytes(32)
-  d['hashMerkle'] = vds.read_bytes(32)
-  d['nTime'] = vds.read_int32()
-  d['nBits'] = vds.read_int32()
-  d['nNonce'] = vds.read_int32()
-  header_end = vds.read_cursor
-  d['__header__'] = vds.input[header_start:header_end]
-  return d
-
-def dump_block(datadir, db_env, block_hash):
-  """ Dump a block, given hexadecimal hash-- either the full hash
-      OR a short_hex version of the it.
-  """
-  db = _open_blkindex(db_env)
-
-  kds = BCDataStream()
-  vds = BCDataStream()
-
-  n_blockindex = 0
-
-  key_prefix = "\x0ablockindex"
-  cursor = db.cursor()
-  (key, value) = cursor.set_range(key_prefix)
-
-  while key.startswith(key_prefix):
-    kds.clear(); kds.write(key)
-    vds.clear(); vds.write(value)
-
-    type = kds.read_string()
-    hash256 = kds.read_bytes(32)
-    hash_hex = long_hex(hash256[::-1])
-    block_data = _parse_block_index(vds)
-
-    if (hash_hex.startswith(block_hash) or short_hex(hash256[::-1]).startswith(block_hash)):
-      print "Block height: "+str(block_data['nHeight'])
-      _dump_block(datadir, block_data['nFile'], block_data['nBlockPos'], hash256, block_data['hashNext'])
-
-    (key, value) = cursor.next()
-
-  db.close()
-
-def read_block(db_cursor, hash):
-  (key,value) = db_cursor.set_range("\x0ablockindex"+hash)
-  vds = BCDataStream()
-  vds.clear(); vds.write(value)
-  block_data = _parse_block_index(vds)
-  block_data['hash256'] = hash
-  return block_data
-
-def scan_blocks(datadir, db_env, callback_fn):
-  """ Scan through blocks, from last through genesis block,
-      calling callback_fn(block_data) for each.
-      callback_fn should return False if scanning should
-      stop, True if it should continue.
-      Returns last block_data scanned.
-  """
-  db = _open_blkindex(db_env)
-
-  kds = BCDataStream()
-  vds = BCDataStream()
-  
-  # Read the hashBestChain record:
-  cursor = db.cursor()
-  (key, value) = cursor.set_range("\x0dhashBestChain")
-  vds.write(value)
-  hashBestChain = vds.read_bytes(32)
-
-  block_data = read_block(cursor, hashBestChain)
-
-  while callback_fn(block_data):
-    if block_data['nHeight'] == 0:
-      break;
-    block_data = read_block(cursor, block_data['hashPrev'])
-  return block_data
-
-
-def dump_block_n(datadir, db_env, block_number):
-  """ Dump a block given block number (== height, genesis block is 0)
-  """
-  def scan_callback(block_data):
-    return not block_data['nHeight'] == block_number
-
-  block_data = scan_blocks(datadir, db_env, scan_callback)
-
-  print "Block height: "+str(block_data['nHeight'])
-  _dump_block(datadir, block_data['nFile'], block_data['nBlockPos'], block_data['hash256'], block_data['hashNext'])
-
-def search_blocks(datadir, db_env, pattern):
-  """ Dump a block given block number (== height, genesis block is 0)
-  """
-  db = _open_blkindex(db_env)
-  kds = BCDataStream()
-  vds = BCDataStream()
-  
-  # Read the hashBestChain record:
-  cursor = db.cursor()
-  (key, value) = cursor.set_range("\x0dhashBestChain")
-  vds.write(value)
-  hashBestChain = vds.read_bytes(32)
-  block_data = read_block(cursor, hashBestChain)
-
-  if pattern == "NONSTANDARD_CSCRIPTS": # Hack to look for non-standard transactions
-    search_odd_scripts(datadir, cursor, block_data)
-    return
-
-  while True:
-    block_string = _dump_block(datadir, block_data['nFile'], block_data['nBlockPos'],
-                               block_data['hash256'], block_data['hashNext'], False)
-    
-    if re.search(pattern, block_string) is not None:
-      print "MATCH: Block height: "+str(block_data['nHeight'])
-      print block_string
-
-    if block_data['nHeight'] == 0:
-      break
-    block_data = read_block(cursor, block_data['hashPrev'])
-    
-def search_odd_scripts(datadir, cursor, block_data):
-  """ Look for non-standard transactions """
-  while True:
-    block_string = _dump_block(datadir, block_data['nFile'], block_data['nBlockPos'],
-                               block_data['hash256'], block_data['hashNext'], False)
-    
-    found_nonstandard = False
-    for m in re.finditer(r'TxIn:(.*?)$', block_string, re.MULTILINE):
-      s = m.group(1)
-      if re.match(r'\s*COIN GENERATED coinbase:\w+$', s): continue
-      if re.match(r'.*sig: \d+:\w+...\w+ \d+:\w+...\w+$', s): continue
-      if re.match(r'.*sig: \d+:\w+...\w+$', s): continue
-      print "Nonstandard TxIn: "+s
-      found_nonstandard = True
-      break
-
-    for m in re.finditer(r'TxOut:(.*?)$', block_string, re.MULTILINE):
-      s = m.group(1)
-      if re.match(r'.*Script: DUP HASH160 \d+:\w+...\w+ EQUALVERIFY CHECKSIG$', s): continue
-      if re.match(r'.*Script: \d+:\w+...\w+ CHECKSIG$', s): continue
-      print "Nonstandard TxOut: "+s
-      found_nonstandard = True
-      break
-
-    if found_nonstandard:
-      print "NONSTANDARD TXN: Block height: "+str(block_data['nHeight'])
-      print block_string
-
-    if block_data['nHeight'] == 0:
-      break
-    block_data = read_block(cursor, block_data['hashPrev'])
-  
-def check_block_chain(db_env):
-  """ Make sure hashPrev/hashNext pointers are consistent through block chain """
-  db = _open_blkindex(db_env)
-
-  kds = BCDataStream()
-  vds = BCDataStream()
-  
-  # Read the hashBestChain record:
-  cursor = db.cursor()
-  (key, value) = cursor.set_range("\x0dhashBestChain")
-  vds.write(value)
-  hashBestChain = vds.read_bytes(32)
-
-  back_blocks = []
-
-  block_data = read_block(cursor, hashBestChain)
-
-  while block_data['nHeight'] > 0:
-    back_blocks.append( (block_data['nHeight'], block_data['hashMerkle'], block_data['hashPrev'], block_data['hashNext']) )
-    block_data = read_block(cursor, block_data['hashPrev'])
-
-  back_blocks.append( (block_data['nHeight'], block_data['hashMerkle'], block_data['hashPrev'], block_data['hashNext']) )
-  genesis_block = block_data
-  
-  print("check block chain: genesis block merkle hash is: %s"%(block_data['hashMerkle'][::-1].encode('hex_codec')))
-
-  while block_data['hashNext'] != ('\0'*32):
-    forward = (block_data['nHeight'], block_data['hashMerkle'], block_data['hashPrev'], block_data['hashNext'])
-    back = back_blocks.pop()
-    if forward != back:
-      print("Forward/back block mismatch at height %d!"%(block_data['nHeight'],))
-      print(" Forward: "+str(forward))
-      print(" Back: "+str(back))
-    block_data = read_block(cursor, block_data['hashNext'])
diff --git a/bitcointools/blocks.py b/bitcointools/blocks.py
deleted file mode 100644 (file)
index 8384751..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-#
-# Code for parsing the blkindex.dat file
-#
-
-from bsddb.db import *
-import logging
-from operator import itemgetter
-import sys
-import time
-
-from BCDataStream import *
-from base58 import public_key_to_bc_address
-from util import short_hex
-from deserialize import *
-
-def _read_CDiskTxPos(stream):
-  n_file = stream.read_uint32()
-  n_block_pos = stream.read_uint32()
-  n_tx_pos = stream.read_uint32()
-  return (n_file, n_block_pos, n_tx_pos)
-
-def dump_blockindex(db_env, owner=None, n_to_dump=1000):
-  db = DB(db_env)
-  r = db.open("blkindex.dat", "main", DB_BTREE, DB_THREAD|DB_RDONLY)
-  if r is not None:
-    logging.error("Couldn't open blkindex.dat/main")
-    sys.exit(1)
-
-  kds = BCDataStream()
-  vds = BCDataStream()
-
-  wallet_transactions = []
-
-  for (i, (key, value)) in enumerate(db.items()):
-    if i > n_to_dump:
-      break
-
-    kds.clear(); kds.write(key)
-    vds.clear(); vds.write(value)
-
-    type = kds.read_string()
-
-    if type == "tx":
-      hash256 = kds.read_bytes(32)
-      version = vds.read_uint32()
-      tx_pos = _read_CDiskTxPos(vds)
-      print("Tx(%s:%d %d %d)"%((short_hex(hash256),)+tx_pos))
-      n_tx_out = vds.read_compact_size()
-      for i in range(0,n_tx_out):
-        tx_out = _read_CDiskTxPos(vds)
-        if tx_out[0] != 0xffffffffL:  # UINT_MAX means no TxOuts (unspent)
-          print("  ==> TxOut(%d %d %d)"%tx_out)
-      
-    else:
-      logging.warn("blkindex: type %s"%(type,))
-      continue
-
-  db.close()
-
diff --git a/bitcointools/dbdump.py b/bitcointools/dbdump.py
deleted file mode 100755 (executable)
index 79340da..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-#!/usr/bin/env python
-#
-# Code for dumping the bitcoin Berkeley db files in a human-readable format
-#
-from bsddb.db import *
-import logging
-import sys
-
-from address import dump_addresses
-from wallet import dump_wallet, dump_accounts
-from blkindex import dump_blkindex_summary
-from transaction import dump_transaction
-from block import dump_block, dump_block_n, search_blocks, check_block_chain
-from util import determine_db_dir, create_env
-
-def main():
-  import optparse
-  parser = optparse.OptionParser(usage="%prog [options]")
-  parser.add_option("--datadir", dest="datadir", default=None,
-                    help="Look for files here (defaults to bitcoin default)")
-  parser.add_option("--wallet", action="store_true", dest="dump_wallet", default=False,
-                    help="Print out contents of the wallet.dat file")
-  parser.add_option("--wallet-tx", action="store_true", dest="dump_wallet_tx", default=False,
-                    help="Print transactions in the wallet.dat file")
-  parser.add_option("--wallet-tx-filter", action="store", dest="wallet_tx_filter", default="",
-                    help="Only print transactions that match given string/regular expression")
-  parser.add_option("--accounts", action="store_true", dest="dump_accounts", default="",
-                    help="Print out account names, one per line")
-  parser.add_option("--blkindex", action="store_true", dest="dump_blkindex", default=False,
-                    help="Print out summary of blkindex.dat file")
-  parser.add_option("--check-block-chain", action="store_true", dest="check_chain", default=False,
-                    help="Scan back and forward through the block chain, looking for inconsistencies")
-  parser.add_option("--address", action="store_true", dest="dump_addr", default=False,
-                    help="Print addresses in the addr.dat file")
-  parser.add_option("--transaction", action="store", dest="dump_transaction", default=None,
-                    help="Dump a single transaction, given hex transaction id (or abbreviated id)")
-  parser.add_option("--block", action="store", dest="dump_block", default=None,
-                    help="Dump a single block, given its hex hash (or abbreviated hex hash) OR block height")
-  parser.add_option("--search-blocks", action="store", dest="search_blocks", default=None,
-                    help="Search the block chain for blocks containing given regex pattern")
-  (options, args) = parser.parse_args()
-
-  if options.datadir is None:
-    db_dir = determine_db_dir()
-  else:
-    db_dir = options.datadir
-
-  try:
-    db_env = create_env(db_dir)
-  except DBNoSuchFileError:
-    logging.error("Couldn't open " + db_dir)
-    sys.exit(1)
-
-  dump_tx = options.dump_wallet_tx
-  if len(options.wallet_tx_filter) > 0:
-    dump_tx = True
-  if options.dump_wallet or dump_tx:
-    dump_wallet(db_env, options.dump_wallet, dump_tx, options.wallet_tx_filter)
-  if options.dump_accounts:
-    dump_accounts(db_env)
-
-  if options.dump_addr:
-    dump_addresses(db_env)
-
-  if options.check_chain:
-    check_block_chain(db_env)
-
-  if options.dump_blkindex:
-    dump_blkindex_summary(db_env)
-
-  if options.dump_transaction is not None:
-    dump_transaction(db_dir, db_env, options.dump_transaction)
-
-  if options.dump_block is not None:
-    if len(options.dump_block) < 7: # Probably an integer...
-      try:
-        dump_block_n(db_dir, db_env, int(options.dump_block))
-      except ValueError:
-        dump_block(db_dir, db_env, options.dump_block)
-    else:
-      dump_block(db_dir, db_env, options.dump_block)
-
-  if options.search_blocks is not None:
-    search_blocks(db_dir, db_env, options.search_blocks)
-
-  db_env.close()
-
-if __name__ == '__main__':
-    main()
diff --git a/bitcointools/deserialize.py b/bitcointools/deserialize.py
deleted file mode 100644 (file)
index a1764da..0000000
+++ /dev/null
@@ -1,303 +0,0 @@
-#
-#
-#
-
-from BCDataStream import *
-from enumeration import Enumeration
-from base58 import public_key_to_bc_address, hash_160_to_bc_address
-import socket
-import time
-from util import short_hex, long_hex
-
-def parse_CAddress(vds):
-  d = {}
-  d['nVersion'] = vds.read_int32()
-  d['nTime'] = vds.read_uint32()
-  d['nServices'] = vds.read_uint64()
-  d['pchReserved'] = vds.read_bytes(12)
-  d['ip'] = socket.inet_ntoa(vds.read_bytes(4))
-  d['port'] = vds.read_uint16()
-  return d
-
-def deserialize_CAddress(d):
-  return d['ip']+":"+str(d['port'])+" (lastseen: %s)"%(time.ctime(d['nTime']),)
-
-def parse_setting(setting, vds):
-  if setting[0] == "f":  # flag (boolean) settings
-    return str(vds.read_boolean())
-  elif setting == "addrIncoming":
-    return "" # bitcoin 0.4 purposely breaks addrIncoming setting in encrypted wallets.
-  elif setting[0:4] == "addr": # CAddress
-    d = parse_CAddress(vds)
-    return deserialize_CAddress(d)
-  elif setting == "nTransactionFee":
-    return vds.read_int64()
-  elif setting == "nLimitProcessors":
-    return vds.read_int32()
-  return 'unknown setting'
-
-def parse_TxIn(vds):
-  d = {}
-  d['prevout_hash'] = vds.read_bytes(32)
-  d['prevout_n'] = vds.read_uint32()
-  d['scriptSig'] = vds.read_bytes(vds.read_compact_size())
-  d['sequence'] = vds.read_uint32()
-  return d
-def deserialize_TxIn(d, transaction_index=None, owner_keys=None):
-  if d['prevout_hash'] == "\x00"*32:
-    result = "TxIn: COIN GENERATED"
-    result += " coinbase:"+d['scriptSig'].encode('hex_codec')
-  elif transaction_index is not None and d['prevout_hash'] in transaction_index:
-    p = transaction_index[d['prevout_hash']]['txOut'][d['prevout_n']]
-    result = "TxIn: value: %f"%(p['value']/1.0e8,)
-    result += " prev("+long_hex(d['prevout_hash'][::-1])+":"+str(d['prevout_n'])+")"
-  else:
-    result = "TxIn: prev("+long_hex(d['prevout_hash'][::-1])+":"+str(d['prevout_n'])+")"
-    pk = extract_public_key(d['scriptSig'])
-    result += " pubkey: "+pk
-    result += " sig: "+decode_script(d['scriptSig'])
-  if d['sequence'] < 0xffffffff: result += " sequence: "+hex(d['sequence'])
-  return result
-
-def parse_TxOut(vds):
-  d = {}
-  d['value'] = vds.read_int64()
-  d['scriptPubKey'] = vds.read_bytes(vds.read_compact_size())
-  return d
-
-def deserialize_TxOut(d, owner_keys=None):
-  result =  "TxOut: value: %f"%(d['value']/1.0e8,)
-  pk = extract_public_key(d['scriptPubKey'])
-  result += " pubkey: "+pk
-  result += " Script: "+decode_script(d['scriptPubKey'])
-  if owner_keys is not None:
-    if pk in owner_keys: result += " Own: True"
-    else: result += " Own: False"
-  return result
-
-def parse_Transaction(vds):
-  d = {}
-  d['version'] = vds.read_int32()
-  n_vin = vds.read_compact_size()
-  d['txIn'] = []
-  for i in xrange(n_vin):
-    d['txIn'].append(parse_TxIn(vds))
-  n_vout = vds.read_compact_size()
-  d['txOut'] = []
-  for i in xrange(n_vout):
-    d['txOut'].append(parse_TxOut(vds))
-  d['lockTime'] = vds.read_uint32()
-  return d
-def deserialize_Transaction(d, transaction_index=None, owner_keys=None):
-  result = "%d tx in, %d out\n"%(len(d['txIn']), len(d['txOut']))
-  for txIn in d['txIn']:
-    result += deserialize_TxIn(txIn, transaction_index) + "\n"
-  for txOut in d['txOut']:
-    result += deserialize_TxOut(txOut, owner_keys) + "\n"
-  return result
-
-def parse_MerkleTx(vds):
-  d = parse_Transaction(vds)
-  d['hashBlock'] = vds.read_bytes(32)
-  n_merkleBranch = vds.read_compact_size()
-  d['merkleBranch'] = vds.read_bytes(32*n_merkleBranch)
-  d['nIndex'] = vds.read_int32()
-  return d
-
-def deserialize_MerkleTx(d, transaction_index=None, owner_keys=None):
-  tx = deserialize_Transaction(d, transaction_index, owner_keys)
-  result = "block: "+(d['hashBlock'][::-1]).encode('hex_codec')
-  result += " %d hashes in merkle branch\n"%(len(d['merkleBranch'])/32,)
-  return result+tx
-
-def parse_WalletTx(vds):
-  d = parse_MerkleTx(vds)
-  n_vtxPrev = vds.read_compact_size()
-  d['vtxPrev'] = []
-  for i in xrange(n_vtxPrev):
-    d['vtxPrev'].append(parse_MerkleTx(vds))
-
-  d['mapValue'] = {}
-  n_mapValue = vds.read_compact_size()
-  for i in xrange(n_mapValue):
-    key = vds.read_string()
-    value = vds.read_string()
-    d['mapValue'][key] = value
-  n_orderForm = vds.read_compact_size()
-  d['orderForm'] = []
-  for i in xrange(n_orderForm):
-    first = vds.read_string()
-    second = vds.read_string()
-    d['orderForm'].append( (first, second) )
-  d['fTimeReceivedIsTxTime'] = vds.read_uint32()
-  d['timeReceived'] = vds.read_uint32()
-  d['fromMe'] = vds.read_boolean()
-  d['spent'] = vds.read_boolean()
-
-  return d
-
-def deserialize_WalletTx(d, transaction_index=None, owner_keys=None):
-  result = deserialize_MerkleTx(d, transaction_index, owner_keys)
-  result += "%d vtxPrev txns\n"%(len(d['vtxPrev']),)
-  result += "mapValue:"+str(d['mapValue'])
-  if len(d['orderForm']) > 0:
-    result += "\n"+" orderForm:"+str(d['orderForm'])
-  result += "\n"+"timeReceived:"+time.ctime(d['timeReceived'])
-  result += " fromMe:"+str(d['fromMe'])+" spent:"+str(d['spent'])
-  return result
-
-# The CAuxPow (auxiliary proof of work) structure supports merged mining.
-# A flag in the block version field indicates the structure's presence.
-# As of 8/2011, the Original Bitcoin Client does not use it.  CAuxPow
-# originated in Namecoin; see
-# https://github.com/vinced/namecoin/blob/mergedmine/doc/README_merged-mining.md.
-def parse_AuxPow(vds):
-  d = parse_MerkleTx(vds)
-  n_chainMerkleBranch = vds.read_compact_size()
-  d['chainMerkleBranch'] = vds.read_bytes(32*n_chainMerkleBranch)
-  d['chainIndex'] = vds.read_int32()
-  d['parentBlock'] = parse_BlockHeader(vds)
-  return d
-
-def parse_BlockHeader(vds):
-  d = {}
-  header_start = vds.read_cursor
-  d['version'] = vds.read_int32()
-  d['hashPrev'] = vds.read_bytes(32)
-  d['hashMerkleRoot'] = vds.read_bytes(32)
-  d['nTime'] = vds.read_uint32()
-  d['nBits'] = vds.read_uint32()
-  d['nNonce'] = vds.read_uint32()
-  header_end = vds.read_cursor
-  d['__header__'] = vds.input[header_start:header_end]
-  return d
-
-def parse_Block(vds):
-  d = parse_BlockHeader(vds)
-  if d['version'] & (1 << 8):
-    d['auxpow'] = parse_AuxPow(vds)
-  d['transactions'] = []
-  nTransactions = vds.read_compact_size()
-  for i in xrange(nTransactions):
-    d['transactions'].append(parse_Transaction(vds))
-
-  return d
-  
-def deserialize_Block(d):
-  result = "Time: "+time.ctime(d['nTime'])+" Nonce: "+str(d['nNonce'])
-  result += "\nnBits: 0x"+hex(d['nBits'])
-  result += "\nhashMerkleRoot: 0x"+d['hashMerkleRoot'][::-1].encode('hex_codec')
-  result += "\nPrevious block: "+d['hashPrev'][::-1].encode('hex_codec')
-  result += "\n%d transactions:\n"%len(d['transactions'])
-  for t in d['transactions']:
-    result += deserialize_Transaction(t)+"\n"
-  result += "\nRaw block header: "+d['__header__'].encode('hex_codec')
-  return result
-
-def parse_BlockLocator(vds):
-  d = { 'hashes' : [] }
-  nHashes = vds.read_compact_size()
-  for i in xrange(nHashes):
-    d['hashes'].append(vds.read_bytes(32))
-  return d
-
-def deserialize_BlockLocator(d):
-  result = "Block Locator top: "+d['hashes'][0][::-1].encode('hex_codec')
-  return result
-
-opcodes = Enumeration("Opcodes", [
-    ("OP_0", 0), ("OP_PUSHDATA1",76), "OP_PUSHDATA2", "OP_PUSHDATA4", "OP_1NEGATE", "OP_RESERVED",
-    "OP_1", "OP_2", "OP_3", "OP_4", "OP_5", "OP_6", "OP_7",
-    "OP_8", "OP_9", "OP_10", "OP_11", "OP_12", "OP_13", "OP_14", "OP_15", "OP_16",
-    "OP_NOP", "OP_VER", "OP_IF", "OP_NOTIF", "OP_VERIF", "OP_VERNOTIF", "OP_ELSE", "OP_ENDIF", "OP_VERIFY",
-    "OP_RETURN", "OP_TOALTSTACK", "OP_FROMALTSTACK", "OP_2DROP", "OP_2DUP", "OP_3DUP", "OP_2OVER", "OP_2ROT", "OP_2SWAP",
-    "OP_IFDUP", "OP_DEPTH", "OP_DROP", "OP_DUP", "OP_NIP", "OP_OVER", "OP_PICK", "OP_ROLL", "OP_ROT",
-    "OP_SWAP", "OP_TUCK", "OP_CAT", "OP_SUBSTR", "OP_LEFT", "OP_RIGHT", "OP_SIZE", "OP_INVERT", "OP_AND",
-    "OP_OR", "OP_XOR", "OP_EQUAL", "OP_EQUALVERIFY", "OP_RESERVED1", "OP_RESERVED2", "OP_1ADD", "OP_1SUB", "OP_2MUL",
-    "OP_2DIV", "OP_NEGATE", "OP_ABS", "OP_NOT", "OP_0NOTEQUAL", "OP_ADD", "OP_SUB", "OP_MUL", "OP_DIV",
-    "OP_MOD", "OP_LSHIFT", "OP_RSHIFT", "OP_BOOLAND", "OP_BOOLOR",
-    "OP_NUMEQUAL", "OP_NUMEQUALVERIFY", "OP_NUMNOTEQUAL", "OP_LESSTHAN",
-    "OP_GREATERTHAN", "OP_LESSTHANOREQUAL", "OP_GREATERTHANOREQUAL", "OP_MIN", "OP_MAX",
-    "OP_WITHIN", "OP_RIPEMD160", "OP_SHA1", "OP_SHA256", "OP_HASH160",
-    "OP_HASH256", "OP_CODESEPARATOR", "OP_CHECKSIG", "OP_CHECKSIGVERIFY", "OP_CHECKMULTISIG",
-    "OP_CHECKMULTISIGVERIFY",
-    ("OP_SINGLEBYTE_END", 0xF0),
-    ("OP_DOUBLEBYTE_BEGIN", 0xF000),
-    "OP_PUBKEY", "OP_PUBKEYHASH",
-    ("OP_INVALIDOPCODE", 0xFFFF),
-])
-
-def script_GetOp(bytes):
-  i = 0
-  while i < len(bytes):
-    vch = None
-    opcode = ord(bytes[i])
-    i += 1
-    if opcode >= opcodes.OP_SINGLEBYTE_END:
-      opcode <<= 8
-      opcode |= bytes[i]
-      i += 1
-
-    if opcode <= opcodes.OP_PUSHDATA4:
-      nSize = opcode
-      if opcode == opcodes.OP_PUSHDATA1:
-        nSize = ord(bytes[i])
-        i += 1
-      elif opcode == opcodes.OP_PUSHDATA2:
-        nSize = unpack_from('<H', bytes, i)
-        i += 2
-      elif opcode == opcodes.OP_PUSHDATA4:
-        nSize = unpack_from('<I', bytes, i)
-        i += 4
-      vch = bytes[i:i+nSize]
-      i += nSize
-
-    yield (opcode, vch)
-
-def script_GetOpName(opcode):
-  return (opcodes.whatis(opcode)).replace("OP_", "")
-
-def decode_script(bytes):
-  result = ''
-  for (opcode, vch) in script_GetOp(bytes):
-    if len(result) > 0: result += " "
-    if opcode <= opcodes.OP_PUSHDATA4:
-      result += "%d:"%(opcode,)
-      result += short_hex(vch)
-    else:
-      result += script_GetOpName(opcode)
-  return result
-
-def match_decoded(decoded, to_match):
-  if len(decoded) != len(to_match):
-    return False;
-  for i in range(len(decoded)):
-    if to_match[i] == opcodes.OP_PUSHDATA4 and decoded[i][0] <= opcodes.OP_PUSHDATA4:
-      continue  # Opcodes below OP_PUSHDATA4 all just push data onto stack, and are equivalent.
-    if to_match[i] != decoded[i][0]:
-      return False
-  return True
-
-def extract_public_key(bytes):
-  decoded = [ x for x in script_GetOp(bytes) ]
-
-  # non-generated TxIn transactions push a signature
-  # (seventy-something bytes) and then their public key
-  # (65 bytes) onto the stack:
-  match = [ opcodes.OP_PUSHDATA4, opcodes.OP_PUSHDATA4 ]
-  if match_decoded(decoded, match):
-    return public_key_to_bc_address(decoded[1][1])
-
-  # The Genesis Block, self-payments, and pay-by-IP-address payments look like:
-  # 65 BYTES:... CHECKSIG
-  match = [ opcodes.OP_PUSHDATA4, opcodes.OP_CHECKSIG ]
-  if match_decoded(decoded, match):
-    return public_key_to_bc_address(decoded[0][1])
-
-  # Pay-by-Bitcoin-address TxOuts look like:
-  # DUP HASH160 20 BYTES:... EQUALVERIFY CHECKSIG
-  match = [ opcodes.OP_DUP, opcodes.OP_HASH160, opcodes.OP_PUSHDATA4, opcodes.OP_EQUALVERIFY, opcodes.OP_CHECKSIG ]
-  if match_decoded(decoded, match):
-    return hash_160_to_bc_address(decoded[2][1])
-
-  return "(None)"
diff --git a/bitcointools/enumeration.py b/bitcointools/enumeration.py
deleted file mode 100644 (file)
index d3d2612..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-#
-# enum-like type
-# From the Python Cookbook, downloaded from http://code.activestate.com/recipes/67107/
-#
-import types, string, exceptions
-
-class EnumException(exceptions.Exception):
-    pass
-
-class Enumeration:
-    def __init__(self, name, enumList):
-        self.__doc__ = name
-        lookup = { }
-        reverseLookup = { }
-        i = 0
-        uniqueNames = [ ]
-        uniqueValues = [ ]
-        for x in enumList:
-            if type(x) == types.TupleType:
-                x, i = x
-            if type(x) != types.StringType:
-                raise EnumException, "enum name is not a string: " + x
-            if type(i) != types.IntType:
-                raise EnumException, "enum value is not an integer: " + i
-            if x in uniqueNames:
-                raise EnumException, "enum name is not unique: " + x
-            if i in uniqueValues:
-                raise EnumException, "enum value is not unique for " + x
-            uniqueNames.append(x)
-            uniqueValues.append(i)
-            lookup[x] = i
-            reverseLookup[i] = x
-            i = i + 1
-        self.lookup = lookup
-        self.reverseLookup = reverseLookup
-    def __getattr__(self, attr):
-        if not self.lookup.has_key(attr):
-            raise AttributeError
-        return self.lookup[attr]
-    def whatis(self, value):
-        return self.reverseLookup[value]
diff --git a/bitcointools/fixwallet.py b/bitcointools/fixwallet.py
deleted file mode 100755 (executable)
index dda57a4..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-#!/usr/bin/env python
-#
-# Recover from a semi-corrupt wallet
-#
-from bsddb.db import *
-import logging
-import sys
-
-from wallet import rewrite_wallet, trim_wallet
-from util import determine_db_dir, create_env
-
-def main():
-  import optparse
-  parser = optparse.OptionParser(usage="%prog [options]")
-  parser.add_option("--datadir", dest="datadir", default=None,
-                    help="Look for files here (defaults to bitcoin default)")
-  parser.add_option("--out", dest="outfile", default="walletNEW.dat",
-                    help="Name of output file (default: walletNEW.dat)")
-  parser.add_option("--clean", action="store_true", dest="clean", default=False,
-                    help="Clean out old, spent change addresses and transactions")
-  parser.add_option("--skipkey", dest="skipkey",
-                    help="Skip entries with keys that contain given string")
-  parser.add_option("--tweakspent", dest="tweakspent",
-                    help="Tweak transaction to mark unspent")
-  (options, args) = parser.parse_args()
-
-  if options.datadir is None:
-    db_dir = determine_db_dir()
-  else:
-    db_dir = options.datadir
-
-  try:
-    db_env = create_env(db_dir)
-  except DBNoSuchFileError:
-    logging.error("Couldn't open " + db_dir)
-    sys.exit(1)
-
-  if options.clean:
-    trim_wallet(db_env, options.outfile)
-
-  elif options.skipkey:
-    def pre_put_callback(type, data):
-      if options.skipkey in data['__key__']:
-        return False
-      return True
-    rewrite_wallet(db_env, options.outfile, pre_put_callback)
-  elif options.tweakspent:
-    txid = options.tweakspent.decode('hex_codec')[::-1]
-    def tweak_spent_callback(type, data):
-      if txid in data['__key__']:
-        data['__value__'] = data['__value__'][:-1]+'\0'
-      return True
-    rewrite_wallet(db_env, options.outfile, tweak_spent_callback)
-    pass
-  else:
-    rewrite_wallet(db_env, options.outfile)
-
-  db_env.close()
-
-if __name__ == '__main__':
-    main()
diff --git a/bitcointools/jsonToCSV.py b/bitcointools/jsonToCSV.py
deleted file mode 100755 (executable)
index a41ee84..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/env python
-#
-# Reads an array of JSON objects and writes out CSV-format,
-# with key names in first row.
-# Columns will be union of all keys in the objects.
-#
-
-import csv
-import json
-import sys
-
-json_string = sys.stdin.read()
-json_array = json.loads(json_string)
-
-columns = set()
-for item in json_array:
-  columns.update(set(item))
-
-writer = csv.writer(sys.stdout)
-writer.writerow(list(columns))
-for item in json_array:
-  row = []
-  for c in columns:
-    if c in item: row.append(str(item[c]))
-    else: row.append('')
-  writer.writerow(row)
-  
diff --git a/bitcointools/statistics.py b/bitcointools/statistics.py
deleted file mode 100755 (executable)
index fd2c01f..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-#!/usr/bin/env python
-#
-# Read the block database, generate monthly statistics and dump out
-# a CSV file.
-#
-from bsddb.db import *
-from datetime import date
-import logging
-import os
-import sys
-
-from BCDataStream import *
-from block import scan_blocks
-from collections import defaultdict
-from deserialize import parse_Block
-from util import determine_db_dir, create_env
-
-def main():
-  import optparse
-  parser = optparse.OptionParser(usage="%prog [options]")
-  parser.add_option("--datadir", dest="datadir", default=None,
-                    help="Look for files here (defaults to bitcoin default)")
-  (options, args) = parser.parse_args()
-
-  if options.datadir is None:
-    db_dir = determine_db_dir()
-  else:
-    db_dir = options.datadir
-
-  try:
-    db_env = create_env(db_dir)
-  except DBNoSuchFileError:
-    logging.error("Couldn't open " + db_dir)
-    sys.exit(1)
-
-  blockfile = open(os.path.join(db_dir, "blk%04d.dat"%(1,)), "rb")
-  block_datastream = BCDataStream()
-  block_datastream.map_file(blockfile, 0)
-
-  n_transactions = defaultdict(int)
-  v_transactions = defaultdict(float)
-  v_transactions_min = defaultdict(float)
-  v_transactions_max = defaultdict(float)
-  def gather_stats(block_data):
-    block_datastream.seek_file(block_data['nBlockPos'])
-    data = parse_Block(block_datastream)
-    block_date = date.fromtimestamp(data['nTime'])
-    key = "%d-%02d"%(block_date.year, block_date.month)
-    for txn in data['transactions'][1:]:
-      values = []
-      for txout in txn['txOut']:
-        n_transactions[key] += 1
-        v_transactions[key] += txout['value'] 
-        values.append(txout['value'])
-      v_transactions_min[key] += min(values)
-      v_transactions_max[key] += max(values)
-    return True
-
-  scan_blocks(db_dir, db_env, gather_stats)
-
-  db_env.close()
-
-  keys = n_transactions.keys()
-  keys.sort()
-  for k in keys:
-    v = v_transactions[k]/1.0e8
-    v_min = v_transactions_min[k]/1.0e8
-    v_max = v_transactions_max[k]/1.0e8
-    # Columns are:
-    # month n_transactions min max total
-    # ... where min and max add up just the smallest or largest
-    # output in each transaction; the true value of bitcoins
-    # transferred will be somewhere between min and max.
-    # We don't know how many are transfers-to-self, though, and
-    # this will undercount multi-txout-transactions (which is good
-    # right now, because they're mostly used for mining pool
-    # payouts that arguably shouldn't count).
-    print "%s,%d,%.2f,%.2f,%.2f"%(k, n_transactions[k], v_min, v_max, v)
-
-if __name__ == '__main__':
-    main()
diff --git a/bitcointools/testBCDataStream.py b/bitcointools/testBCDataStream.py
deleted file mode 100644 (file)
index 5452340..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#
-# Unit tests for BCDataStream class
-#
-
-import unittest
-
-import BCDataStream
-
-class Tests(unittest.TestCase):
-  def setUp(self):
-    self.ds = BCDataStream.BCDataStream()
-
-  def testString(self):
-    t = {
-      "\x07setting" : "setting",
-      "\xfd\x00\x07setting" : "setting",
-      "\xfe\x00\x00\x00\x07setting" : "setting",
-      }
-    for (input, output) in t.iteritems():
-      self.ds.clear()
-      self.ds.write(input)
-      got = self.ds.read_string()
-      self.assertEqual(output, got)
-
-if __name__ == "__main__":
-  unittest.main()
diff --git a/bitcointools/transaction.py b/bitcointools/transaction.py
deleted file mode 100644 (file)
index 962c8e9..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-#
-# Code for dumping a single transaction, given its ID
-#
-
-from bsddb.db import *
-import logging
-import os.path
-import sys
-import time
-
-from BCDataStream import *
-from base58 import public_key_to_bc_address
-from util import short_hex
-from deserialize import *
-
-def _read_CDiskTxPos(stream):
-  n_file = stream.read_uint32()
-  n_block_pos = stream.read_uint32()
-  n_tx_pos = stream.read_uint32()
-  return (n_file, n_block_pos, n_tx_pos)
-
-def _dump_tx(datadir, tx_hash, tx_pos):
-  blockfile = open(os.path.join(datadir, "blk%04d.dat"%(tx_pos[0],)), "rb")
-  ds = BCDataStream()
-  ds.map_file(blockfile, tx_pos[2])
-  d = parse_Transaction(ds)
-  print deserialize_Transaction(d)
-  ds.close_file()
-  blockfile.close()
-
-def dump_transaction(datadir, db_env, tx_id):
-  """ Dump a transaction, given hexadecimal tx_id-- either the full ID
-      OR a short_hex version of the id.
-  """
-  db = DB(db_env)
-  try:
-    r = db.open("blkindex.dat", "main", DB_BTREE, DB_THREAD|DB_RDONLY)
-  except DBError:
-    r = True
-
-  if r is not None:
-    logging.error("Couldn't open blkindex.dat/main.  Try quitting any running Bitcoin apps.")
-    sys.exit(1)
-
-  kds = BCDataStream()
-  vds = BCDataStream()
-
-  n_tx = 0
-  n_blockindex = 0
-
-  key_prefix = "\x02tx"+(tx_id[-4:].decode('hex_codec')[::-1])
-  cursor = db.cursor()
-  (key, value) = cursor.set_range(key_prefix)
-
-  while key.startswith(key_prefix):
-    kds.clear(); kds.write(key)
-    vds.clear(); vds.write(value)
-
-    type = kds.read_string()
-    hash256 = (kds.read_bytes(32))
-    hash_hex = long_hex(hash256[::-1])
-    version = vds.read_uint32()
-    tx_pos = _read_CDiskTxPos(vds)
-    if (hash_hex.startswith(tx_id) or short_hex(hash256[::-1]).startswith(tx_id)):
-      _dump_tx(datadir, hash256, tx_pos)
-
-    (key, value) = cursor.next()
-
-  db.close()
-
diff --git a/bitcointools/util.py b/bitcointools/util.py
deleted file mode 100644 (file)
index 4f0adfd..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# Misc util routines
-#
-
-from bsddb.db import *
-
-def long_hex(bytes):
-  return bytes.encode('hex_codec')
-
-def short_hex(bytes):
-  t = bytes.encode('hex_codec')
-  if len(t) < 11:
-    return t
-  return t[0:4]+"..."+t[-4:]
-
-def determine_db_dir():
-  import os
-  import os.path
-  import platform
-  if platform.system() == "Darwin":
-    return os.path.expanduser("~/Library/Application Support/Bitcoin/")
-  elif platform.system() == "Windows":
-    return os.path.join(os.environ['APPDATA'], "Bitcoin")
-  return os.path.expanduser("~/.bitcoin")
-
-def create_env(db_dir=None):
-  if db_dir is None:
-    db_dir = determine_db_dir()
-  db_env = DBEnv(0)
-  r = db_env.open(db_dir,
-                  (DB_CREATE|DB_INIT_LOCK|DB_INIT_LOG|DB_INIT_MPOOL|
-                   DB_INIT_TXN|DB_THREAD|DB_RECOVER))
-  return db_env
diff --git a/bitcointools/wallet.py b/bitcointools/wallet.py
deleted file mode 100644 (file)
index a41d3a6..0000000
+++ /dev/null
@@ -1,349 +0,0 @@
-#
-# Code for parsing the wallet.dat file
-#
-
-from bsddb.db import *
-import logging
-import re
-import sys
-import time
-
-from BCDataStream import *
-from base58 import public_key_to_bc_address, bc_address_to_hash_160, hash_160
-from util import short_hex, long_hex
-from deserialize import *
-
-def open_wallet(db_env, writable=False):
-  db = DB(db_env)
-  flags = DB_THREAD | (DB_CREATE if writable else DB_RDONLY)
-  try:
-    r = db.open("wallet.dat", "main", DB_BTREE, flags)
-  except DBError:
-    r = True
-
-  if r is not None:
-    logging.error("Couldn't open wallet.dat/main. Try quitting Bitcoin and running this again.")
-    sys.exit(1)
-  
-  return db
-
-def parse_wallet(db, item_callback):
-  kds = BCDataStream()
-  vds = BCDataStream()
-
-  for (key, value) in db.items():
-    d = { }
-
-    kds.clear(); kds.write(key)
-    vds.clear(); vds.write(value)
-
-    type = kds.read_string()
-
-    d["__key__"] = key
-    d["__value__"] = value
-    d["__type__"] = type
-
-    try:
-      if type == "tx":
-        d["tx_id"] = kds.read_bytes(32)
-        d.update(parse_WalletTx(vds))
-      elif type == "name":
-        d['hash'] = kds.read_string()
-        d['name'] = vds.read_string()
-      elif type == "version":
-        d['version'] = vds.read_uint32()
-      elif type == "setting":
-        d['setting'] = kds.read_string()
-        d['value'] = parse_setting(d['setting'], vds)
-      elif type == "key":
-        d['public_key'] = kds.read_bytes(kds.read_compact_size())
-        d['private_key'] = vds.read_bytes(vds.read_compact_size())
-      elif type == "wkey":
-        d['public_key'] = kds.read_bytes(kds.read_compact_size())
-        d['private_key'] = vds.read_bytes(vds.read_compact_size())
-        d['created'] = vds.read_int64()
-        d['expires'] = vds.read_int64()
-        d['comment'] = vds.read_string()
-      elif type == "ckey":
-        d['public_key'] = kds.read_bytes(kds.read_compact_size())
-        d['crypted_key'] = vds.read_bytes(vds.read_compact_size())
-      elif type == "mkey":
-        d['nID'] = kds.read_int32()
-        d['crypted_key'] = vds.read_bytes(vds.read_compact_size())
-        d['salt'] = vds.read_bytes(vds.read_compact_size())
-        d['nDerivationMethod'] = vds.read_int32()
-        d['nDeriveIterations'] = vds.read_int32()
-        d['vchOtherDerivationParameters'] = vds.read_bytes(vds.read_compact_size())
-      elif type == "defaultkey":
-        d['key'] = vds.read_bytes(vds.read_compact_size())
-      elif type == "pool":
-        d['n'] = kds.read_int64()
-        d['nVersion'] = vds.read_int32()
-        d['nTime'] = vds.read_int64()
-        d['public_key'] = vds.read_bytes(vds.read_compact_size())
-      elif type == "acc":
-        d['account'] = kds.read_string()
-        d['nVersion'] = vds.read_int32()
-        d['public_key'] = vds.read_bytes(vds.read_compact_size())
-      elif type == "acentry":
-        d['account'] = kds.read_string()
-        d['n'] = kds.read_uint64()
-        d['nVersion'] = vds.read_int32()
-        d['nCreditDebit'] = vds.read_int64()
-        d['nTime'] = vds.read_int64()
-        d['otherAccount'] = vds.read_string()
-        d['comment'] = vds.read_string()
-      elif type == "bestblock":
-        d['nVersion'] = vds.read_int32()
-        d.update(parse_BlockLocator(vds))
-      else:
-        print "Unknown key type: "+type
-      
-      item_callback(type, d)
-
-    except Exception, e:
-      print("ERROR parsing wallet.dat, type %s"%type)
-      print("key data in hex: %s"%key.encode('hex_codec'))
-      print("value data in hex: %s"%value.encode('hex_codec'))
-  
-def update_wallet(db, type, data):
-  """Write a single item to the wallet.
-  db must be open with writable=True.
-  type and data are the type code and data dictionary as parse_wallet would
-  give to item_callback.
-  data's __key__, __value__ and __type__ are ignored; only the primary data
-  fields are used.
-  """
-  d = data
-  kds = BCDataStream()
-  vds = BCDataStream()
-
-  # Write the type code to the key
-  kds.write_string(type)
-  vds.write("")             # Ensure there is something
-
-  try:
-    if type == "tx":
-      raise NotImplementedError("Writing items of type 'tx'")
-      kds.write(d['tx_id'])
-      #d.update(parse_WalletTx(vds))
-    elif type == "name":
-      kds.write(d['hash'])
-      vds.write(d['name'])
-    elif type == "version":
-      vds.write_uint32(d['version'])
-    elif type == "setting":
-      raise NotImplementedError("Writing items of type 'setting'")
-      kds.write_string(d['setting'])
-      #d['value'] = parse_setting(d['setting'], vds)
-    elif type == "key":
-      kds.write_string(d['public_key'])
-      vds.write_string(d['private_key'])
-    elif type == "wkey":
-      kds.write_string(d['public_key'])
-      vds.write_string(d['private_key'])
-      vds.write_int64(d['created'])
-      vds.write_int64(d['expires'])
-      vds.write_string(d['comment'])
-    elif type == "ckey":
-      kds.write_string(d['public_key'])
-      kds.write_string(d['crypted_key'])
-    elif type == "mkey":
-      kds.write_int32(d['nID'])
-      vds.write_string(d['crypted_key'])
-      vds.write_string(d['salt'])
-      vds.write_int32(d['nDeriveIterations'])
-      vds.write_int32(d['nDerivationMethod'])
-      vds.write_string(d['vchOtherDerivationParameters'])
-    elif type == "defaultkey":
-      vds.write_string(d['key'])
-    elif type == "pool":
-      kds.write_int64(d['n'])
-      vds.write_int32(d['nVersion'])
-      vds.write_int64(d['nTime'])
-      vds.write_string(d['public_key'])
-    elif type == "acc":
-      kds.write_string(d['account'])
-      vds.write_int32(d['nVersion'])
-      vds.write_string(d['public_key'])
-    elif type == "acentry":
-      kds.write_string(d['account'])
-      kds.write_uint64(d['n'])
-      vds.write_int32(d['nVersion'])
-      vds.write_int64(d['nCreditDebit'])
-      vds.write_int64(d['nTime'])
-      vds.write_string(d['otherAccount'])
-      vds.write_string(d['comment'])
-    elif type == "bestblock":
-      vds.write_int32(d['nVersion'])
-      vds.write_compact_size(len(d['hashes']))
-      for h in d['hashes']:
-        vds.write(h)
-    else:
-      print "Unknown key type: "+type
-
-    # Write the key/value pair to the database
-    db.put(kds.input, vds.input)
-
-  except Exception, e:
-    print("ERROR writing to wallet.dat, type %s"%type)
-    print("data dictionary: %r"%data)
-
-def dump_wallet(db_env, print_wallet, print_wallet_transactions, transaction_filter):
-  db = open_wallet(db_env)
-
-  wallet_transactions = []
-  transaction_index = { }
-  owner_keys = { }
-
-  def item_callback(type, d):
-    if type == "tx":
-      wallet_transactions.append( d )
-      transaction_index[d['tx_id']] = d
-    elif type == "key":
-      owner_keys[public_key_to_bc_address(d['public_key'])] = d['private_key']
-    elif type == "ckey":
-      owner_keys[public_key_to_bc_address(d['public_key'])] = d['crypted_key']
-
-    if not print_wallet:
-      return
-    if type == "tx":
-      return
-    elif type == "name":
-      print("ADDRESS "+d['hash']+" : "+d['name'])
-    elif type == "version":
-      print("Version: %d"%(d['version'],))
-    elif type == "setting":
-      print(d['setting']+": "+str(d['value']))
-    elif type == "key":
-      print("PubKey "+ short_hex(d['public_key']) + " " + public_key_to_bc_address(d['public_key']) +
-            ": PriKey "+ short_hex(d['private_key']))
-    elif type == "wkey":
-      print("WPubKey 0x"+ short_hex(d['public_key']) + " " + public_key_to_bc_address(d['public_key']) +
-            ": WPriKey 0x"+ short_hex(d['crypted_key']))
-      print(" Created: "+time.ctime(d['created'])+" Expires: "+time.ctime(d['expires'])+" Comment: "+d['comment'])
-    elif type == "ckey":
-      print("PubKey "+ short_hex(d['public_key']) + " " + public_key_to_bc_address(d['public_key']) +
-            ": Encrypted PriKey "+ short_hex(d['crypted_key']))
-    elif type == "mkey":
-      print("Master Key %d"%(d['nID']) + ": 0x"+ short_hex(d['crypted_key']) +
-            ", Salt: 0x"+ short_hex(d['salt']) +
-            ". Passphrase hashed %d times with method %d with other parameters 0x"%(d['nDeriveIterations'], d['nDerivationMethod']) +
-            long_hex(d['vchOtherDerivationParameters']))
-    elif type == "defaultkey":
-      print("Default Key: 0x"+ short_hex(d['key']) + " " + public_key_to_bc_address(d['key']))
-    elif type == "pool":
-      print("Change Pool key %d: %s (Time: %s)"% (d['n'], public_key_to_bc_address(d['public_key']), time.ctime(d['nTime'])))
-    elif type == "acc":
-      print("Account %s (current key: %s)"%(d['account'], public_key_to_bc_address(d['public_key'])))
-    elif type == "acentry":
-      print("Move '%s' %d (other: '%s', time: %s, entry %d) %s"%
-            (d['account'], d['nCreditDebit'], d['otherAccount'], time.ctime(d['nTime']), d['n'], d['comment']))
-    elif type == "bestblock":
-      print deserialize_BlockLocator(d)
-    else:
-      print "Unknown key type: "+type
-
-  parse_wallet(db, item_callback)
-
-  if print_wallet_transactions:
-    keyfunc = lambda i: i['timeReceived']
-    for d in sorted(wallet_transactions, key=keyfunc):
-      tx_value = deserialize_WalletTx(d, transaction_index, owner_keys)
-      if len(transaction_filter) > 0 and re.search(transaction_filter, tx_value) is None: continue
-
-      print("==WalletTransaction== "+long_hex(d['tx_id'][::-1]))
-      print(tx_value)
-
-  db.close()
-
-def dump_accounts(db_env):
-  db = open_wallet(db_env)
-
-  kds = BCDataStream()
-  vds = BCDataStream()
-
-  accounts = set()
-
-  for (key, value) in db.items():
-    kds.clear(); kds.write(key)
-    vds.clear(); vds.write(value)
-
-    type = kds.read_string()
-
-    if type == "acc":
-      accounts.add(kds.read_string())
-    elif type == "name":
-      accounts.add(vds.read_string())
-    elif type == "acentry":
-      accounts.add(kds.read_string())
-      # Note: don't need to add otheraccount, because moves are
-      # always double-entry
-
-  for name in sorted(accounts):
-    print(name)
-
-  db.close()
-
-def rewrite_wallet(db_env, destFileName, pre_put_callback=None):
-  db = open_wallet(db_env)
-
-  db_out = DB(db_env)
-  try:
-    r = db_out.open(destFileName, "main", DB_BTREE, DB_CREATE)
-  except DBError:
-    r = True
-
-  if r is not None:
-    logging.error("Couldn't open %s."%destFileName)
-    sys.exit(1)
-
-  def item_callback(type, d):
-    if (pre_put_callback is None or pre_put_callback(type, d)):
-      db_out.put(d["__key__"], d["__value__"])
-
-  parse_wallet(db, item_callback)
-
-  db_out.close()
-  db.close()
-
-def trim_wallet(db_env, destFileName, pre_put_callback=None):
-  """Write out ONLY address book public/private keys
-     THIS WILL NOT WRITE OUT 'change' KEYS-- you should
-     send all of your bitcoins to one of your public addresses
-     before calling this.
-  """
-  db = open_wallet(db_env)
-  
-  pubkeys = []
-  def gather_pubkeys(type, d):
-    if type == "name":
-      pubkeys.append(bc_address_to_hash_160(d['hash']))
-  
-  parse_wallet(db, gather_pubkeys)
-
-  db_out = DB(db_env)
-  try:
-    r = db_out.open(destFileName, "main", DB_BTREE, DB_CREATE)
-  except DBError:
-    r = True
-
-  if r is not None:
-    logging.error("Couldn't open %s."%destFileName)
-    sys.exit(1)
-
-  def item_callback(type, d):
-    should_write = False
-    if type in [ 'version', 'name', 'acc' ]:
-      should_write = True
-    if type in [ 'key', 'wkey', 'ckey' ] and hash_160(d['public_key']) in pubkeys:
-      should_write = True
-    if pre_put_callback is not None:
-      should_write = pre_put_callback(type, d, pubkeys)
-    if should_write:
-      db_out.put(d["__key__"], d["__value__"])
-
-  parse_wallet(db, item_callback)
-
-  db_out.close()
-  db.close()