Exemple #1
0
class VarstrScriptSerializer(Serializer):
    def __init__(self):
        self.serializer = ScriptSerializer()
        self.strencoder = VarstrSerializer()

    def serialize(self, script):
        scriptstr = self.serializer.serialize(script)
        return (self.strencoder.serialize(scriptstr))

    def get_size(self, script):
        return self.strencoder.get_size_for_len(self.serializer.get_size(script))

    def deserialize(self, data, cursor=0):
        scriptstr, newcursor = self.strencoder.deserialize(data, cursor)
        return (self.serializer.deserialize(scriptstr), newcursor)
class VarstrScriptSerializer(Serializer):
    def __init__(self):
        self.serializer = ScriptSerializer()
        self.strencoder = VarstrSerializer()

    def serialize(self, script):
        scriptstr = self.serializer.serialize(script)
        return (self.strencoder.serialize(scriptstr))

    def get_size(self, script):
        return self.strencoder.get_size_for_len(
            self.serializer.get_size(script))

    def deserialize(self, data, cursor=0):
        scriptstr, newcursor = self.strencoder.deserialize(data, cursor)
        return (self.serializer.deserialize(scriptstr), newcursor)
Exemple #3
0
class BSDDBWalletDatabase(WalletDatabaseInterface):
    def __init__(self, bsddb_env, filename):
        self.bsddb_env = bsddb_env
        self.filename = filename
        self.varstr_serializer = VarstrSerializer()
        self.uint256_serializer = Uint256Serializer("")
        self.wallet_tx_serializer = WalletTxSerializer()
        self.master_key_serializer = MasterKeySerializer()
        self.reset_wallet()
        self.db = bsddb.db.DB(self.bsddb_env.dbenv)
        self.dbflags = bsddb.db.DB_THREAD

    def open(self):
        #self.bsddb_env.dbenv.fileid_reset(self.filename)
        self.dbtxn = self.bsddb_env.dbenv.txn_begin()
        self.db.open(self.filename,
                     "main",
                     bsddb.db.DB_BTREE,
                     self.dbflags,
                     txn=self.dbtxn)
        self.dbtxn.commit()
        self.dbtxn = None
        self._read_wallet()

    def create(self):
        #create empty database
        self.dbtxn = self.bsddb_env.dbenv.txn_begin()
        self.db.open(self.filename,
                     "main",
                     bsddb.db.DB_BTREE,
                     self.dbflags | bsddb.db.DB_CREATE,
                     txn=self.dbtxn)
        self.dbtxn.commit()
        self.dbtxn = None

    def begin_updates(self):
        self.dbtxn = self.bsddb_env.dbenv.txn_begin()

    def commit_updates(self):
        self.dbtxn.commit()
        #Synch to disk as wallet changes should not be lost
        self.db.sync()
        self.dbtxn = None

    def get_receive_key(self):
        if len(self.poolkeys) == 0:
            raise Exception("get_receive_key: No keys remaining")
        num, poolkey = next(self.poolkeys.iteritems())
        return poolkey.public_key

    def allocate_key(self, public_key, address, label=None, ischange=False):
        num = self.poolkeys_by_public_key[public_key].poolnum
        if num is None:
            raise Exception("allocate_pool_key: Can't find pool public_key")
        del self.poolkeys_by_public_key[public_key]
        del self.poolkeys[num]
        self.db.delete("\x04pool" + struct.pack("<q", num), txn=self.dbtxn)

        if (label and not ischange):
            self.set_label(address, label)

    def reset_wallet(self):
        self.master_keys = {}
        self.crypted_keys = {}
        self.keys = {}
        self.names = {}
        self.settings = []
        self.txs = {}
        self.poolkeys = {}
        self.poolkeys_by_public_key = {}

    def _read_entries(self, label):
        for key, value in self.db.items():
            lab, key_cursor = self.varstr_serializer.deserialize(key, 0)
            if lab == label:
                yield (key, key_cursor, value, 0)

    def _read_keys(self):
        for key, key_cursor, value, value_cursor in self._read_entries("key"):
            public_key, _ = self.varstr_serializer.deserialize(key, key_cursor)
            private_key, _ = self.varstr_serializer.deserialize(
                value, value_cursor)
            self.keys[public_key] = WalletKeypair(public_key, private_key)

    def _read_crypted_keys(self):
        for key, key_cursor, value, value_cursor in self._read_entries("ckey"):
            public_key, _ = self.varstr_serializer.deserialize(key, key_cursor)
            crypted_secret, _ = self.varstr_serializer.deserialize(
                value, value_cursor)
            self.crypted_keys[public_key] = crypted_secret

    def _read_master_keys(self):
        for key, key_cursor, value, value_cursor in self._read_entries("mkey"):
            id, = struct.unpack_from("<I", key, key_cursor)
            self.master_keys[
                id], cursor = self.master_key_serializer.deserialize(
                    value, value_cursor)

    def _read_names(self):
        for key, key_cursor, value, value_cursor in self._read_entries("name"):
            address_bytestr, _ = self.varstr_serializer.deserialize(
                key, key_cursor)
            name, _ = self.varstr_serializer.deserialize(value, value_cursor)
            address = BitcoinAddress.from_base58addr(address_bytestr)
            self.names[address] = WalletName(name, address)

    def _read_txs(self):
        for key, key_cursor, value, value_cursor in self._read_entries("tx"):
            hash, _ = self.uint256_serializer.deserialize(key, key_cursor)
            wallet_tx, _ = self.wallet_tx_serializer.deserialize(
                value, value_cursor)
            self.txs[hash] = wallet_tx

    def _read_poolkeys(self):
        for key, key_cursor, value, value_cursor in self._read_entries("pool"):
            poolnum, = struct.unpack_from("<q", key, key_cursor)
            version, = struct.unpack_from("<I", value, 0)
            time, = struct.unpack_from("<q", value, 4)
            public_key, _ = self.varstr_serializer.deserialize(value, 12)
            self.poolkeys[poolnum] = WalletPoolKey(poolnum, version, time,
                                                   public_key)
            self.poolkeys_by_public_key[public_key] = self.poolkeys[poolnum]

    def _read_wallet(self):
        self.reset_wallet()
        self._read_keys()
        self._read_crypted_keys()
        self._read_master_keys()
        self._read_names()
        self._read_txs()
        self._read_poolkeys()

    def get_keys(self):
        return self.keys

    def get_crypted_keys(self):
        return self.crypted_keys

    def get_wallet_txs(self):
        return self.txs

    def get_names(self):
        return self.names

    def get_poolkeys(self):
        return self.poolkeys

    def add_poolkey(self, poolkey):
        self.db.put("\x04pool" + struct.pack("<q", poolkey.poolnum),
                    struct.pack("<I", poolkey.version) + \
                    struct.pack("<q", poolkey.time) + \
                    self.varstr_serializer.serialize(poolkey.public_key),
                    txn=self.dbtxn)
        self.poolkeys[poolkey.poolnum] = poolkey
        self.poolkeys_by_public_key[poolkey.public_key] = self.poolkeys[
            poolkey.poolnum]

    def set_label(self, address, label):
        self.names[address] = WalletName(label, address)
        address = self.varstr_serializer.serialize(address.to_base58addr())
        name = self.varstr_serializer.serialize(label)
        self.db.put("\x04name" + address, name, txn=self.dbtxn)

    def add_name(self, wallet_name):
        pass

    def add_keypair(self, wallet_keypair):
        pass

    def set_transaction(self, hashtx, wallet_tx):
        self.txs[hashtx] = wallet_tx
        key = self.uint256_serializer.serialize(hashtx)
        value = self.wallet_tx_serializer.serialize(wallet_tx)
        self.db.put("\x02tx" + key, value, txn=self.dbtxn)

    def get_transaction(self, hashtx):
        return self.txs[hashtx]

    def del_transaction(self, hashtx):
        del self.txs[hashtx]
        self.db.delete("\x02tx" + self.uint256_serializer.serialize(hashtx),
                       txn=self.dbtxn)

    def del_poolkey(self, num):
        del self.poolkeys[num]
        self.db.delete("\x04pool" + struct.pack("<I", num))

    def add_master_key(self, master_key):
        id = max(self.master_keys.keys() + [0]) + 1
        key = "\x04mkey" + struct.pack("<I", id)
        value = self.master_key_serializer.serialize(master_key)
        self.db.put(key, value, txn=self.dbtxn)
        self.master_keys[id] = master_key

    def add_crypted_key(self, public_key, crypted_secret):
        self.db.put("\x04ckey" + self.varstr_serializer.serialize(public_key),
                    self.varstr_serializer.serialize(crypted_secret),
                    txn=self.dbtxn)
        self.crypted_keys[public_key] = crypted_secret

    def get_master_keys(self):
        return (self.master_keys)

    def get_version(self):
        return (struct.unpack("<I", self.db["\x07version"])[0])

    def set_version(self, version):
        self.db["\x07version"] = struct.pack("<I", version)

    """ Return wallet's BlockLocator or None if not found """

    def get_block_locator(self):
        if self.db.has_key("\x09bestblock"):
            serializer = BlockLocatorSerializer()
            block_locator, cursor = serializer.deserialize(
                self.db["\x09bestblock"], 0)
            return block_locator

    def set_blocklocator(self, blocklocator):
        serializer = BlockLocatorSerializer()
        self.db["\x09bestblock"] = serializer.serialize(blocklocator)

    def __str__(self):
        keys_str = "\n".join("    " + str(k) for k in self.get_keypairs())
        pool_keys_str = "\n".join("    " + str(k) for k in self.get_poolkeys())
        names_str = "\n".join("    " + str(k) for k in self.get_names())
        tx_str = "\n".join("    " + str(k) for k in self.get_wallet_txs())
        return "Wallet\n  keys:\n" + keys_str + "pool:\n" + pool_keys_str + "\n  names:\n" + names_str + "\n  txs:\n" + tx_str
class BSDDBWalletDatabase(WalletDatabaseInterface):
    def __init__(self, bsddb_env, filename):
        self.bsddb_env = bsddb_env
        self.filename = filename
        self.varstr_serializer = VarstrSerializer()
        self.uint256_serializer = Uint256Serializer("")
        self.wallet_tx_serializer = WalletTxSerializer()
        self.master_key_serializer = MasterKeySerializer()
        self.reset_wallet()
        self.db = bsddb.db.DB(self.bsddb_env.dbenv)
        self.dbflags = bsddb.db.DB_THREAD

    def open(self):
        # self.bsddb_env.dbenv.fileid_reset(self.filename)
        self.dbtxn = self.bsddb_env.dbenv.txn_begin()
        self.db.open(self.filename, "main", bsddb.db.DB_BTREE, self.dbflags, txn=self.dbtxn)
        self.dbtxn.commit()
        self.dbtxn = None
        self._read_wallet()

    def create(self):
        # create empty database
        self.dbtxn = self.bsddb_env.dbenv.txn_begin()
        self.db.open(self.filename, "main", bsddb.db.DB_BTREE, self.dbflags | bsddb.db.DB_CREATE, txn=self.dbtxn)
        self.dbtxn.commit()
        self.dbtxn = None

    def begin_updates(self):
        self.dbtxn = self.bsddb_env.dbenv.txn_begin()

    def commit_updates(self):
        self.dbtxn.commit()
        # Synch to disk as wallet changes should not be lost
        self.db.sync()
        self.dbtxn = None

    def get_receive_key(self):
        if len(self.poolkeys) == 0:
            raise Exception("get_receive_key: No keys remaining")
        num, poolkey = next(self.poolkeys.iteritems())
        return poolkey.public_key

    def allocate_key(self, public_key, address, label=None, ischange=False):
        num = self.poolkeys_by_public_key[public_key].poolnum
        if num is None:
            raise Exception("allocate_pool_key: Can't find pool public_key")
        del self.poolkeys_by_public_key[public_key]
        del self.poolkeys[num]
        self.db.delete("\x04pool" + struct.pack("<q", num), txn=self.dbtxn)

        if label and not ischange:
            self.set_label(address, label)

    def reset_wallet(self):
        self.master_keys = {}
        self.crypted_keys = {}
        self.keys = {}
        self.names = {}
        self.settings = []
        self.txs = {}
        self.poolkeys = {}
        self.poolkeys_by_public_key = {}

    def _read_entries(self, label):
        for key, value in self.db.items():
            lab, key_cursor = self.varstr_serializer.deserialize(key, 0)
            if lab == label:
                yield (key, key_cursor, value, 0)

    def _read_keys(self):
        for key, key_cursor, value, value_cursor in self._read_entries("key"):
            public_key, _ = self.varstr_serializer.deserialize(key, key_cursor)
            private_key, _ = self.varstr_serializer.deserialize(value, value_cursor)
            self.keys[public_key] = WalletKeypair(public_key, private_key)

    def _read_crypted_keys(self):
        for key, key_cursor, value, value_cursor in self._read_entries("ckey"):
            public_key, _ = self.varstr_serializer.deserialize(key, key_cursor)
            crypted_secret, _ = self.varstr_serializer.deserialize(value, value_cursor)
            self.crypted_keys[public_key] = crypted_secret

    def _read_master_keys(self):
        for key, key_cursor, value, value_cursor in self._read_entries("mkey"):
            id, = struct.unpack_from("<I", key, key_cursor)
            self.master_keys[id], cursor = self.master_key_serializer.deserialize(value, value_cursor)

    def _read_names(self):
        for key, key_cursor, value, value_cursor in self._read_entries("name"):
            address_bytestr, _ = self.varstr_serializer.deserialize(key, key_cursor)
            name, _ = self.varstr_serializer.deserialize(value, value_cursor)
            address = BitcoinAddress.from_base58addr(address_bytestr)
            self.names[address] = WalletName(name, address)

    def _read_txs(self):
        for key, key_cursor, value, value_cursor in self._read_entries("tx"):
            hash, _ = self.uint256_serializer.deserialize(key, key_cursor)
            wallet_tx, _ = self.wallet_tx_serializer.deserialize(value, value_cursor)
            self.txs[hash] = wallet_tx

    def _read_poolkeys(self):
        for key, key_cursor, value, value_cursor in self._read_entries("pool"):
            poolnum, = struct.unpack_from("<q", key, key_cursor)
            version, = struct.unpack_from("<I", value, 0)
            time, = struct.unpack_from("<q", value, 4)
            public_key, _ = self.varstr_serializer.deserialize(value, 12)
            self.poolkeys[poolnum] = WalletPoolKey(poolnum, version, time, public_key)
            self.poolkeys_by_public_key[public_key] = self.poolkeys[poolnum]

    def _read_wallet(self):
        self.reset_wallet()
        self._read_keys()
        self._read_crypted_keys()
        self._read_master_keys()
        self._read_names()
        self._read_txs()
        self._read_poolkeys()

    def get_keys(self):
        return self.keys

    def get_crypted_keys(self):
        return self.crypted_keys

    def get_wallet_txs(self):
        return self.txs

    def get_names(self):
        return self.names

    def get_poolkeys(self):
        return self.poolkeys

    def add_poolkey(self, poolkey):
        self.db.put(
            "\x04pool" + struct.pack("<q", poolkey.poolnum),
            struct.pack("<I", poolkey.version)
            + struct.pack("<q", poolkey.time)
            + self.varstr_serializer.serialize(poolkey.public_key),
            txn=self.dbtxn,
        )
        self.poolkeys[poolkey.poolnum] = poolkey
        self.poolkeys_by_public_key[poolkey.public_key] = self.poolkeys[poolkey.poolnum]

    def set_label(self, address, label):
        self.names[address] = WalletName(label, address)
        address = self.varstr_serializer.serialize(address.to_base58addr())
        name = self.varstr_serializer.serialize(label)
        self.db.put("\x04name" + address, name, txn=self.dbtxn)

    def add_name(self, wallet_name):
        pass

    def add_keypair(self, wallet_keypair):
        pass

    def set_transaction(self, hashtx, wallet_tx):
        self.txs[hashtx] = wallet_tx
        key = self.uint256_serializer.serialize(hashtx)
        value = self.wallet_tx_serializer.serialize(wallet_tx)
        self.db.put("\x02tx" + key, value, txn=self.dbtxn)

    def get_transaction(self, hashtx):
        return self.txs[hashtx]

    def del_transaction(self, hashtx):
        del self.txs[hashtx]
        self.db.delete("\x02tx" + self.uint256_serializer.serialize(hashtx), txn=self.dbtxn)

    def del_poolkey(self, num):
        del self.poolkeys[num]
        self.db.delete("\x04pool" + struct.pack("<I", num))

    def add_master_key(self, master_key):
        id = max(self.master_keys.keys() + [0]) + 1
        key = "\x04mkey" + struct.pack("<I", id)
        value = self.master_key_serializer.serialize(master_key)
        self.db.put(key, value, txn=self.dbtxn)
        self.master_keys[id] = master_key

    def add_crypted_key(self, public_key, crypted_secret):
        self.db.put(
            "\x04ckey" + self.varstr_serializer.serialize(public_key),
            self.varstr_serializer.serialize(crypted_secret),
            txn=self.dbtxn,
        )
        self.crypted_keys[public_key] = crypted_secret

    def get_master_keys(self):
        return self.master_keys

    def get_version(self):
        return struct.unpack("<I", self.db["\x07version"])[0]

    def set_version(self, version):
        self.db["\x07version"] = struct.pack("<I", version)

    """ Return wallet's BlockLocator or None if not found """

    def get_block_locator(self):
        if self.db.has_key("\x09bestblock"):
            serializer = BlockLocatorSerializer()
            block_locator, cursor = serializer.deserialize(self.db["\x09bestblock"], 0)
            return block_locator

    def set_blocklocator(self, blocklocator):
        serializer = BlockLocatorSerializer()
        self.db["\x09bestblock"] = serializer.serialize(blocklocator)

    def __str__(self):
        keys_str = "\n".join("    " + str(k) for k in self.get_keypairs())
        pool_keys_str = "\n".join("    " + str(k) for k in self.get_poolkeys())
        names_str = "\n".join("    " + str(k) for k in self.get_names())
        tx_str = "\n".join("    " + str(k) for k in self.get_wallet_txs())
        return (
            "Wallet\n  keys:\n"
            + keys_str
            + "pool:\n"
            + pool_keys_str
            + "\n  names:\n"
            + names_str
            + "\n  txs:\n"
            + tx_str
        )