Example #1
0
 def __init__(self, model, config):
     super(VerifiedTxDb, self).__init__(model, config)
     self.bs = self.model.get_blockchain_state()
     self.vbs = VerifiedBlockchainState(
         self.bs, self, config.get('testnet', False),
         os.path.dirname(self.model.store_conn.path))
     self.vbs.start()
     self.lock = threading.Lock()
     self.verified_tx = {}
Example #2
0
 def __init__(self, model, config):
     super(VerifiedTxDb, self).__init__(model, config)
     self.bs = self.model.get_blockchain_state()
     self.vbs = VerifiedBlockchainState(
         self.bs,
         self,
         config.get('testnet', False),
         os.path.dirname(self.model.store_conn.path)
     )
     self.vbs.start()
     self.lock = threading.Lock()
     self.verified_tx = {}
Example #3
0
class VerifiedTxDb(BaseTxDb):
    def __init__(self, model, config):
        super(VerifiedTxDb, self).__init__(model, config)
        self.bs = self.model.get_blockchain_state()
        self.vbs = VerifiedBlockchainState(
            self.bs, self, config.get('testnet', False),
            os.path.dirname(self.model.store_conn.path))
        self.vbs.start()
        self.lock = threading.Lock()
        self.verified_tx = {}

    def __del__(self):
        if self.vbs:
            self.vbs.stop()

    def _get_merkle_root(self, merkle_s, start_hash, pos):
        hash_decode = lambda x: x.decode('hex')[::-1]
        hash_encode = lambda x: x[::-1].encode('hex')

        h = hash_decode(start_hash)
        # i is the "level" or depth of the binary merkle tree.
        # item is the complementary hash on the merkle tree at this level
        for i, item in enumerate(merkle_s):
            # figure out if it's the left item or right item at this level
            if pos >> i & 1:
                # right item (odd at this level)
                h = double_sha256(hash_decode(item) + h)
            else:
                # left item (even at this level)
                h = double_sha256(h + hash_decode(item))
        return hash_encode(h)

    def _verify_merkle(self, txhash):
        result = self.bs.get_merkle(txhash)
        merkle, tx_height, pos = result.get('merkle'), \
            result.get('block_height'), result.get('pos')

        merkle_root = self._get_merkle_root(merkle, txhash, pos)
        header = self.vbs.get_header(tx_height)
        if header is None:
            return False
        if header.get('merkle_root') != merkle_root:
            return False

        with self.lock:
            self.verified_tx[txhash] = tx_height
        return True

    def update_tx_block_height(self, txhash, status):
        with self.lock:
            if txhash in self.verified_tx:
                self.store.set_block_height(txhash, self.verified_tx[txhash])

    def drop_from_height(self, height):
        with self.lock:
            self.verified_tx = {
                key: value
                for key, value in self.verified_tx.items() if value < height
            }

    def get_confirmations(self, txhash):
        with self.lock:
            if txhash in self.verified_tx:
                height = self.verified_tx[txhash]
                return self.vbs.height - height + 1
            else:
                return None

    def identify_tx_status(self, txhash):
        block_hash, in_mempool = self.bs.get_tx_blockhash(txhash)
        if (not block_hash) and (not in_mempool):
            return TX_STATUS_INVALID
        if not block_hash:
            return TX_STATUS_UNCONFIRMED
        confirmations = self.get_confirmations(txhash)
        if confirmations is None:
            verified = self._verify_merkle(txhash)
            if verified:
                return self.identify_tx_status(txhash)
            else:
                return TX_STATUS_UNCONFIRMED
        if confirmations == 0:
            return TX_STATUS_UNCONFIRMED
        return TX_STATUS_CONFIRMED
Example #4
0
class VerifiedTxDb(BaseTxDb):
    def __init__(self, model, config):
        super(VerifiedTxDb, self).__init__(model, config)
        self.bs = self.model.get_blockchain_state()
        self.vbs = VerifiedBlockchainState(
            self.bs,
            self,
            config.get('testnet', False),
            os.path.dirname(self.model.store_conn.path)
        )
        self.vbs.start()
        self.lock = threading.Lock()
        self.verified_tx = {}

    def __del__(self):
        if self.vbs:
            self.vbs.stop()

    def _get_merkle_root(self, merkle_s, start_hash, pos):
        hash_decode = lambda x: x.decode('hex')[::-1]
        hash_encode = lambda x: x[::-1].encode('hex')

        h = hash_decode(start_hash)
        # i is the "level" or depth of the binary merkle tree.
        # item is the complementary hash on the merkle tree at this level
        for i, item in enumerate(merkle_s):
            # figure out if it's the left item or right item at this level
            if pos >> i & 1:
                # right item (odd at this level)
                h = double_sha256(hash_decode(item) + h)
            else:
                # left item (even at this level)
                h = double_sha256(h + hash_decode(item))
        return hash_encode(h)

    def _verify_merkle(self, txhash):
        result = self.bs.get_merkle(txhash)
        merkle, tx_height, pos = result.get('merkle'), \
            result.get('block_height'), result.get('pos')

        merkle_root = self._get_merkle_root(merkle, txhash, pos)
        header = self.vbs.get_header(tx_height)
        if header is None:
            return False
        if header.get('merkle_root') != merkle_root:
            return False

        with self.lock:
            self.verified_tx[txhash] = tx_height
        return True

    def update_tx_block_height(self, txhash, status):
        with self.lock:
            if txhash in self.verified_tx:
                self.store.set_block_height(txhash,
                                            self.verified_tx[txhash])

    def drop_from_height(self, height):
        with self.lock:
            self.verified_tx = {key: value for key, value in self.verified_tx.items() if value < height}

    def get_confirmations(self, txhash):
        with self.lock:
            if txhash in self.verified_tx:
                height = self.verified_tx[txhash]
                return self.vbs.height - height + 1
            else:
                return None

    def identify_tx_status(self, txhash):
        block_hash, in_mempool = self.bs.get_tx_blockhash(txhash)
        if (not block_hash) and (not in_mempool):
            return TX_STATUS_INVALID
        if not block_hash:
            return TX_STATUS_UNCONFIRMED
        confirmations = self.get_confirmations(txhash)
        if confirmations is None:
            verified = self._verify_merkle(txhash)
            if verified:
                return self.identify_tx_status(txhash)
            else:
                return TX_STATUS_UNCONFIRMED
        if confirmations == 0:
            return TX_STATUS_UNCONFIRMED
        return TX_STATUS_CONFIRMED