def __init__(self): self._bucket = Bucket(Blockchain.db_file, Blockchain.block_bucket) try: self._tip = self._bucket.get('l') except KeyError: self._tip = None
def __init__(self, address=None): self._bucket = Bucket(Blockchain.db_file, Blockchain.block_bucket) try: self._tip = self._bucket.get('l') except KeyError: genesis = NewGnesisBlock().pow_of_block() self._block_put(genesis)
def reset(self): self._bucket = Bucket(UTXOSet.db_file, UTXOSet.bucket) self._bucket.reset() utxos = self._bc.find_all_utxo() for tx_id, vout_idx in utxos.items(): self._bucket.put(tx_id, utils.serialize(vout_idx)) self._bucket.commit()
def __init__(self, address=None): self._bucket = Bucket(Blockchain.db_file, Blockchain.block_bucket) try: self._tip = self._bucket.get('l') except KeyError: cb_tx = CoinbaseTx(address, Blockchain.genesis_coinbase_data) genesis = Block([cb_tx]).pow_of_block() self._block_put(genesis)
def __init__(self, address=None): self._bucket = Bucket(BlockChain.db_file, BlockChain.block_bucket) try: self._tip = self._bucket.get('l') except KeyError: if not address: self._tip = None else: cb_tx = CoinbaseTx(address, BlockChain.genesis_coinbase_data) genesis = Block([cb_tx], 0).proof_of_block() self._put_block(genesis)
def __init__(self, address=None): self._bucket = Bucket(BlockChain.db_file, BlockChain.bucket) try: self._address = self._bucket.get('address') self._last_hash = self._bucket.get('l') self._last_block = pickle.loads(self._bucket.get(self._last_hash)) except KeyError: if not address: # no data & no given address print('Block Chain not created yet!\nPlease create a new block chain with given address first!') sys.exit() else: self.reset(address)
class Blockchain(object): """ Represents a sequence of blocks Args: None Attributes: None """ def __init__(self): self._blocks = Bucket(DB_FILE, BLOCK_BUCKET) def __repr__(self): return 'Blockchain({0!r})'.format(self._blocks) def __str__(self): self._blocks.commit() return 'Blockchain({0!r})'.format(self._blocks) def addBlock(self, transaction): prevBlock = self._blocks[len(self._blocks) - 1] self._blocks.append( Block(prevBlock.height, prevBlock.hash, transaction)) self._blocks.commit() def printBlock(self, height): block = self._blocks[height] print(block) self._blocks.commit()
def update(self, block): self._bucket = Bucket(UTXOSet.db_file, UTXOSet.bucket) transactions = block.transactions for tx in transactions: if not isinstance(tx, CoinBaseTx): for vin in tx.vin: update_outs = [] encoded_outs = self._bucket.get(vin.txid) outs = utils.deserialize(encoded_outs) for out_idx, out in enumerate(outs): if out_idx != vin.vout_idx: update_outs.append(out) if len(update_outs) == 0: self._bucket.delete(vin.txid) else: self._bucket.put( vin.txid, utils.serialize(update_outs)) new_output = [out for out in tx.vout] self._bucket.put(tx.id, utils.serialize(new_output)) self._bucket.commit()
class Blockchain(object): """ Blockchain keeps a sequence of Blocks Attributes: _tip (bytes): Point to the latest hash of block. _bucket (dict): bucket of DB """ latest = 'l' db_file = 'blockchain.db' block_bucket = 'blocks' genesis_coinbase_data = 'The Times 03/Jan/2009 Chancellor on brink of second bailout for banks' def __init__(self, address=None): self._bucket = Bucket(Blockchain.db_file, Blockchain.block_bucket) try: self._tip = self._bucket.get('l') except KeyError: genesis = NewGnesisBlock().pow_of_block() self._block_put(genesis) # if not address: # self._tip = None # else: # genesis = NewGnesisBlock().pow_of_block() # self._block_put(genesis) def _block_put(self, block): self._bucket.put(block.hash, block.serialize()) self._bucket.put('l', block.hash) self._tip = block.hash self._bucket.commit() @property def blocks(self): current_tip = self._tip while True: if not current_tip: # Encounter genesis block raise StopIteration encoded_block = self._bucket.get(current_tip) block = pickle.loads(encoded_block) yield block current_tip = block.prev_block_hash @property def length(self): return len(list(self.blocks))
class BlockChain(): latest = 'l' latest_height = 'height' db_file = "blockchain.db" block_bucket = 'blocks' genesis_coinbase_data = 'The Times 03/Jan/2009 Chancellor on brink of second bailout for banks' def __init__(self, address=None): self._bucket = Bucket(BlockChain.db_file, BlockChain.block_bucket) try: self._tip = self._bucket.get('l') except KeyError: if not address: self._tip = None else: cb_tx = CoinbaseTx(address, BlockChain.genesis_coinbase_data) genesis = Block([cb_tx], 0).proof_of_block() self._put_block(genesis) def _put_block(self, block): self._bucket.put(block.hash, block.serialize()) self._bucket.put('l', block.hash) self._bucket.put('height', block.height) self._tip = block.hash self._bucket.save() def MineBlock(self, tx_lst): last_hash = self._bucket.get('l') last_height = self._bucket.get('height') for tx in tx_lst: if not self.verify_transaction(tx): print("ERROR: Invalid transaction") sys.exit() new_block = Block(tx_lst, last_height + 1, last_hash).proof_of_block() self._put_block(new_block) return new_block def find_unspent_transactions(self, pubkey_hash): spent_txo = defaultdict(list) unspent_txs = [] for block in blocks: for tx in block.transactions: if not isinstance(tx, CoinbaseTx): for vin in tx.vin: if vin.uses_key(pubkey_hash): spent_txo[tx.id].append(vin.vout) for out_idx, out in enumerate(tx.vout): if spent_txo[tx.id]: for spent_out in spent_txo[tx.id]: if spent_out == out_idx: continue if out.is_locked_with_key(pubkey_hash): unspent_txs.append(tx) break return unspent_txs def find_utxo(self): utxo = defaultdict(list) spent_txos = defaultdict(list) for block in self.blocks(): for tx in block.transactions: for out_idx, out in enumerate(tx.vout): if spent_txos[tx.id]: for spent_out in spent_txos[tx.id]: if spent_out == out_idx: continue utxo[tx.id].append(out) if not isinstance(tx, CoinbaseTx): for vin in tx.vin: spent_txos[vin.txid].append(vin.vout) return utxo def blocks(self, height=None): cur_tip = self._tip while True: if not cur_tip: break encoded_block = self._bucket.get(cur_tip) block = pickle.loads(encoded_block) cur_tip = block.prev_block_hash cur_height = block.height if height is not None: if cur_height == height: yield block return elif cur_height < height: raise IndexError(height) else: continue yield block def find_transaction(self, ID): for block in self.blocks(): for tx in block.transactions: if tx.id == ID: return tx return None def sign_transaction(self, tx, priv_key): prev_txs = {} for vin in tx.vin: prev_tx = self.find_transaction(vin.txid) prev_txs[prev_tx.id] = prev_tx tx.sign(priv_key, prev_txs) def verify_transaction(self, tx): if isinstance(tx, CoinbaseTx): return True prev_txs = {} for vin in tx.vin: prev_tx = self.find_transaction(vin.txid) prev_txs[prev_tx.id] = prev_tx return tx.verify(prev_txs)
class UTXOSet(object): db_file = 'blockchain.db' utxo_bucket = 'utxo' def __init__(self, blockchain): self._bucket = Bucket(UTXOSet.db_file, UTXOSet.utxo_bucket) self._bc = blockchain @property def blockchain(self): return self._bc def reindex(self): # Rebuilds the UTXO set self._bucket.reset() utxos = self._bc.find_utxo() for tx_id, outs in utxos.items(): self._bucket.put(tx_id, utils.serialize(outs)) self._bucket.commit() def find_spendable_outputs(self, pubkey_hash, amount): # Finds and returns unspent outputs to reference in inputs accumulated = 0 unspent_outputs = defaultdict(list) for tx_id, outs in self._bucket.kv.items(): outs = utils.deserialize(outs) for out_idx, out in enumerate(outs): if out.is_locked_with_key(pubkey_hash) and accumulated < amount: accumulated += out.value unspent_outputs[tx_id].append(out_idx) return accumulated, unspent_outputs def find_utxo(self, pubkey_hash): # Finds UTXO for a public key hash utxos = [] for _, outs in self._bucket.kv.items(): outs = utils.deserialize(outs) for out in outs: if out.is_locked_with_key(pubkey_hash): utxos.append(out) return utxos def print_utxo(self): utxos = [] for _, outs in self._bucket.kv.items(): outs = utils.deserialize(outs) for out in outs: print(out) def count_transactions(self): # Returns the number of transactions in the UTXO set return len(self._bucket) def update(self, block): # Updates the UTXO set with transactions from the Block for tx in block.transactions: if not isinstance(tx, CoinbaseTx): for vin in tx.vin: update_outs = [] outs_bytes = self._bucket.get(vin.tx_id) outs = utils.deserialize(outs_bytes) for out_idx, out in enumerate(outs): if out_idx != vin.vout: update_outs.append(out) if len(update_outs) == 0: self._bucket.delete(vin.tx_id) else: self._bucket.put( vin.tx_id, utils.serialize(update_outs)) # Add new outputs new_outputs = [out for out in tx.vout] self._bucket.put(tx.ID, utils.serialize(new_outputs)) self._bucket.commit() @property def utxo_set(self): return {k: utils.deserialize(v) for k, v in self._bucket.kv.items()}
class BlockChain(object): bucket = 'blocks' db_file = 'block_chain.db' genesis_block_data = 'This is a Genesis block!' def __init__(self, address=None): self._bucket = Bucket(BlockChain.db_file, BlockChain.bucket) try: self._address = self._bucket.get('address') self._last_hash = self._bucket.get('l') self._last_block = pickle.loads(self._bucket.get(self._last_hash)) except KeyError: if not address: # no data & no given address print('Block Chain not created yet!\nPlease create a new block chain with given address first!') sys.exit() else: self.reset(address) def _put_block(self, block): self._last_block = block self._last_hash = block.hash self._bucket.put('l', block.hash) self._bucket.put(block.hash, block.serialize()) self._bucket.commit() def add_block(self, transactions): ''' Args: transactions (list): List of transactions ''' current_height = self._last_block.height new_block = Block(current_height+1, self._last_hash, transactions) new_block.set_hash() self._put_block(new_block) def reset(self, address): self._bucket.reset() coinbaseTx = CoinBaseTx(address) genesis_block = Block(0, '', [coinbaseTx]) genesis_block.set_hash() self._put_block(genesis_block) self._address = address self._last_block = genesis_block self._last_hash = genesis_block.hash self._bucket.put('address', address) self._bucket.commit() return self @property def blocks(self): current_hash = self._last_hash while current_hash: encoded_block = self._bucket.get(current_hash) block = pickle.loads(encoded_block) yield block current_hash = block.prev_hash @property def address(self): return self._address @property def last_block(self): return self._last_block @property def last_hash(self): return self._last_hash def print_all_blocks(self): for block in self.blocks: block.print_block() def print_block_with_height(self, height): for block in self.blocks: if block.height == height: block.print_block() return print('No block with height {} found!'.format(height)) def find_all_utxo(self): utxo = defaultdict(list) stxo = defaultdict(list) for block in self.blocks: for tx in block.transactions: try: for out_idx, out in enumerate(tx.vout): if stxo[tx.id]: for spent_out in stxo[tx.id]: if spent_out == out_idx: raise utils.ContinueIt utxo[tx.id].append(out) except utils.ContinueIt: pass if not isinstance(tx, CoinBaseTx): for vin in tx.vin: stxo[tx.id].append(vin.vout_idx) return utxo
class UTXOSet(object): ''' Maintain all UTXOs in current blockchain ''' db_file = 'block_chain.db' bucket = 'utxo' def __init__(self, block_chain): self._bucket = Bucket(UTXOSet.db_file, UTXOSet.bucket) self._bc = block_chain def reset(self): self._bucket = Bucket(UTXOSet.db_file, UTXOSet.bucket) self._bucket.reset() utxos = self._bc.find_all_utxo() for tx_id, vout_idx in utxos.items(): self._bucket.put(tx_id, utils.serialize(vout_idx)) self._bucket.commit() def update(self, block): self._bucket = Bucket(UTXOSet.db_file, UTXOSet.bucket) transactions = block.transactions for tx in transactions: if not isinstance(tx, CoinBaseTx): for vin in tx.vin: update_outs = [] encoded_outs = self._bucket.get(vin.txid) outs = utils.deserialize(encoded_outs) for out_idx, out in enumerate(outs): if out_idx != vin.vout_idx: update_outs.append(out) if len(update_outs) == 0: self._bucket.delete(vin.txid) else: self._bucket.put( vin.txid, utils.serialize(update_outs)) new_output = [out for out in tx.vout] self._bucket.put(tx.id, utils.serialize(new_output)) self._bucket.commit() def find_spendable_output(self, address, amount): accumulate = 0 spendable_output = defaultdict(list) for tx_id, outs in self._bucket.kv.items(): outs = utils.deserialize(outs) for out_idx, out in enumerate(outs): if out.address == address: accumulate += out.value spendable_output[tx_id].append(out_idx) if accumulate >= amount: return accumulate, spendable_output return accumulate, spendable_output def find_utxo_by_address(self, address): accumulate = 0 utxos = defaultdict(list) for tx_id, outs in self._bucket.kv.items(): outs = utils.deserialize(outs) for out_idx, out in enumerate(outs): if out.address == address: accumulate += out.value utxos[tx_id].append(out_idx) return accumulate, utxos
from block import Block from blockchain import Blockchain from db import Bucket if __name__ == "__main__": # blockchain = Blockchain() # print(blockchain) # blockchain.addBlock('addBlock') # print(blockchain) bucket = Bucket('test.db', 'block') bucket2 = Bucket('test.db', 'block2') bucket['key1'] = 'value' print(bucket['key']) bucket2['key2'] = 'value' bucket.commit() bucket2.commit() print(bucket) print(bucket2)
class Blockchain(object): """ Blockchain keeps a sequence of Blocks Attributes: _tip (bytes): Point to the latest hash of block. _bucket (dict): bucket of DB """ latest = 'l' db_file = 'blockchain.db' block_bucket = 'blocks' genesis_coinbase_data = 'The Times 03/Jan/2009 Chancellor on brink of second bailout for banks' def __init__(self, address=None): self._bucket = Bucket(Blockchain.db_file, Blockchain.block_bucket) try: self._tip = self._bucket.get('l') except KeyError: if not address: self._tip = None else: cb_tx = CoinbaseTx( address, Blockchain.genesis_coinbase_data) genesis = Block([cb_tx]).pow_of_block() self._block_put(genesis) def _block_put(self, block): self._bucket.put(block.hash, block.serialize()) self._bucket.put('l', block.hash) self._tip = block.hash self._bucket.commit() def MineBlock(self, transaction_lst): # Mines a new block with the provided transactions last_hash = self._bucket.get('l') for tx in transaction_lst: if not self.verify_transaction(tx): print("ERROR: Invalid transaction") sys.exit() new_block = Block(transaction_lst, last_hash).pow_of_block() self._block_put(new_block) return new_block def find_unspent_transactions(self, pubkey_hash): # Returns a list of transactions containing unspent outputs spent_txo = defaultdict(list) unspent_txs = [] for block in self.blocks: for tx in block.transactions: if not isinstance(tx, CoinbaseTx): for vin in tx.vin: if vin.uses_key(pubkey_hash): tx_id = vin.tx_id spent_txo[tx_id].append(vin.vout) tx_id = tx.ID try: for out_idx, out in enumerate(tx.vout): # Was the output spent? if spent_txo[tx_id]: for spent_out in spent_txo[tx_id]: if spent_out == out_idx: raise ContinueIt if out.is_locked_with_key(pubkey_hash): unspent_txs.append(tx) except ContinueIt: pass return unspent_txs def find_utxo(self): # Finds all unspent transaction outputs utxo = defaultdict(list) spent_txos = defaultdict(list) for block in self.blocks: for tx in block.transactions: try: for out_idx, out in enumerate(tx.vout): # Was the output spent? if spent_txos[tx.ID]: for spent_out in spent_txos[tx.ID]: if spent_out == out_idx: raise ContinueIt utxo[tx.ID].append(out) except ContinueIt: pass if not isinstance(tx, CoinbaseTx): for vin in tx.vin: spent_txos[vin.tx_id].append(vin.vout) return utxo @property def blocks(self): current_tip = self._tip while True: if not current_tip: # Encounter genesis block raise StopIteration encoded_block = self._bucket.get(current_tip) block = pickle.loads(encoded_block) yield block current_tip = block.prev_block_hash def find_transaction(self, ID): # finds a transaction by its ID for block in self.blocks: for tx in block.transactions: if tx.ID == ID: return tx # return None raise NotFoundTransaction def sign_transaction(self, tx, priv_key): prev_txs = {} for vin in tx.vin: prev_tx = self.find_transaction(vin.tx_id) prev_txs[prev_tx.ID] = prev_tx tx.sign(priv_key, prev_txs) def verify_transaction(self, tx): if isinstance(tx, CoinbaseTx): return True prev_txs = {} for vin in tx.vin: prev_tx = self.find_transaction(vin.tx_id) prev_txs[prev_tx.ID] = prev_tx return tx.verify(prev_txs)
class Blockchain(object): """ Attributes: _tip (bytes): Point to the latest hash of block. _bucket (dict): bucket of DB """ db_file = 'blockchain.db' block_bucket = 'blocks' genesis_coinbase_data = 'mother f****r first block' def __init__(self, address=None): self._bucket = Bucket(Blockchain.db_file, Blockchain.block_bucket) try: self._tip = self._bucket.get('l') except KeyError: cb_tx = CoinbaseTx(address, Blockchain.genesis_coinbase_data) genesis = Block([cb_tx]).pow_of_block() self._block_put(genesis) def _block_put(self, block): self._bucket.put( block.hash, pickle.dumps(block) ) self._bucket.put('l', block.hash) self._tip = block.hash self._bucket.commit() def MineBlock(self, transaction_lst): # Mines a new block with the provided transactions last_hash = self._bucket.get('l') for tx in transaction_lst: if not self.verify_transaction(tx): print("ERROR: Invalid transaction") sys.exit() print( 'Verifying complete\n' ) new_block = Block(transaction_lst, last_hash).pow_of_block() self._block_put(new_block) return new_block @property def latest_block(self): return pickle.loads( self._bucket.get( self._tip ) ) @property def blocks(self): current_tip = self._tip while True: if not current_tip: raise StopIteration encoded_block = self._bucket.get(current_tip) block = pickle.loads(encoded_block) yield block current_tip = block.prev_block_hash @property def height(self): return len( self._bucket.kv )-1 def find_transaction(self, ID): # finds a transaction by its ID for block in self.blocks: for tx in block.transactions: if tx.ID == ID: return tx return None def sign_transaction(self, tx, priv_key): prev_txs = {} for vin in tx.vin: prev_tx = self.find_transaction(vin.tx_id) prev_txs[prev_tx.ID] = prev_tx tx.sign(priv_key, prev_txs) def verify_transaction(self, tx): if isinstance(tx, CoinbaseTx): return True prev_txs = {} for vin in tx.vin: prev_tx = self.find_transaction(vin.tx_id) prev_txs[prev_tx.ID] = prev_tx return tx.verify(prev_txs)
class Blockchain(object): """ Blockchain keeps a sequence of Blocks Attributes: _tip (bytes): Point to the latest hash of block. _bucket (dict): bucket of DB """ latest = 'l' db_file = GetAppDir() + str(r'\blockchain.db') block_bucket = 'blocks' genesis_coinbase_data = 'The Times 03/Jan/2009 Chancellor on brink of second bailout for banks' def __init__(self): self._bucket = Bucket(Blockchain.db_file, Blockchain.block_bucket) try: self._tip = self._bucket.get('l') except KeyError: self._tip = None def _block_put(self, block): for tx in block._tx_lst: if not self.verify_transaction(tx): utils.logg( 'Verify transactions faild, block contains one or more txs wich cant be verified' ) return False self._bucket.put(block.hash, block.serialize()) self._bucket.put('l', block.hash) self._tip = block.hash return self._bucket.commit() def find_unspent_transactions(self, pubkey_hash): # Returns a list of transactions containing unspent outputs spent_txo = defaultdict(list) unspent_txs = [] for block in self.blocks: for tx in block.transactions: if not isinstance(tx, CoinbaseTx): for vin in tx.vin: if vin.uses_key(pubkey_hash): tx_id = vin.tx_id spent_txo[tx_id].append(vin.vout) tx_id = tx.ID try: for out_idx, out in enumerate(tx.vout): # Was the output spent? if spent_txo[tx_id]: for spent_out in spent_txo[tx_id]: if spent_out == out_idx: raise ContinueIt if out.is_locked_with_key(pubkey_hash): unspent_txs.append(tx) except ContinueIt: pass return unspent_txs def find_utxo(self): # Finds all unspent transaction outputs utxo = defaultdict(list) spent_txos = defaultdict(list) for block in self.blocks: for tx in block.transactions: try: for out_idx, out in enumerate(tx.vout): # Was the output spent? if spent_txos[tx.ID]: for spent_out in spent_txos[tx.ID]: if spent_out == out_idx: raise ContinueIt utxo[tx.ID].append(out) except ContinueIt: pass if not isinstance(tx, CoinbaseTx): for vin in tx.vin: spent_txos[vin.tx_id].append(vin.vout) return utxo @property def blocks(self): current_tip = self._tip while True: if not current_tip: # Encounter genesis block break encoded_block = self._bucket.get(current_tip) block = pickle.loads(encoded_block) yield block current_tip = block.prev_block_hash def haveBlock(self, block_hash): for block in self.blocks: if block.hash == block_hash: return True return False def getBlock(self, block_hash): if self.haveBlock(block_hash): for block in self.blocks: if block.hash == block_hash: return block return None def find_transaction(self, ID): # finds a transaction by its ID for block in self.blocks: for tx in block.transactions: if tx.ID == ID: return tx # return None raise NotFoundTransaction def sign_transaction(self, tx, priv_key): prev_txs = {} for vin in tx.vin: prev_tx = self.find_transaction(vin.tx_id) prev_txs[prev_tx.ID] = prev_tx tx.sign(priv_key, prev_txs) def verify_transaction(self, tx): if tx.isCoinBase(): return True prev_txs = {} for vin in tx.vin: prev_tx = self.find_transaction(vin.tx_id) prev_txs[prev_tx.ID] = prev_tx return tx.verify(prev_txs)
def __init__(self, blockchain): self._bucket = Bucket(UTXOSet.db_file, UTXOSet.utxo_bucket) self._bc = blockchain
class UTXOSet(): db_file = "utxo.db" utxo_bucket = "utxo" def __init__(self, blockchain): self._bucket = Bucket(UTXOSet.db_file, UTXOSet.utxo_bucket) self._bc = blockchain def reindex(self): self._bucket.reset() utxos = self._bc.find_utxo() for txid, outs in utxos.items(): self._bucket.put(txid, utils.serialize(outs)) self._bucket.save() def find_spendable_outputs(self, pubkey_hash, amount): account_amount = 0 unspent_outputs = defaultdict(list) for tx_id, outs in self._bucket.kv.items(): outs = utils.deserialize(outs) for out_idx, out in enumerate(outs): if out.is_locked_with_key( pubkey_hash) and account_amount < amount: account_amount += out.value unspent_outputs[tx_id].append(out_idx) return account_amount, unspent_outputs def update(self, block): for tx in block.transactions: if not isinstance(tx, CoinbaseTx): for vin in tx.vin: update_outs = [] outs_bytes = self._bucket.get(vin.txid) outs = utils.deserialize(outs_bytes) for out_idx, out in enumerate(outs): if out_idx != vin.vout: update_outs.append(out) if len(update_outs) == 0: self._bucket.delete(vin.txid) else: self._bucket.put(vin.txid, utils.serialize(update_outs)) # Add new outputs new_outputs = [out for out in tx.vout] self._bucket.put(tx.id, utils.serialize(new_outputs)) self._bucket.save() def print_utxo(self): utxos = [] for _, outs in self._bucket.kv.items(): outs = utils.deserialize(outs) for out in outs: print(out.value) def find_utxo(self, pubkey_hash): utxos = [] for _, outs in self._bucket.kv.items(): outs = utils.deserialize(outs) for out in outs: if out.is_locked_with_key(pubkey_hash): utxos.append(out) return utxos @property def blockchain(self): return self._bc
def __init__(self): self._blocks = Bucket(DB_FILE, BLOCK_BUCKET)