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 __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 = {}
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
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