def get_key_for_mined_block(self) -> bytes: self.wallet_lock.acquire() public_key = self.wallet.get_annotated_public_key( "reserved for potentially mined block") save_wallet(self.wallet) self.wallet_lock.release() return public_key
def open_or_init_wallet() -> Wallet: if os.path.isfile("wallet.json"): wallet = Wallet.load(open("wallet.json", "r")) else: wallet = Wallet.empty() wallet.generate_keys(10_000) save_wallet(wallet) print("Created new wallet w/ 10.000 keys") return wallet
def handle_scrypt_output_message(self, miner_id: int, data: bytes) -> None: summary_hash: bytes = data self.increment_hash_counter() summary, current_height, transactions = self.mining_args[miner_id] evidence = construct_pow_evidence_after_scrypt(summary_hash, self.coinstate, summary, current_height, transactions) block = Block(BlockHeader(summary, evidence), transactions) if block.hash() >= block.target: # we didn't mine the block return self.network_thread.local_peer.chain_manager.set_coinstate( self.coinstate) self.network_thread.local_peer.network_manager.broadcast_block(block) self.coinstate = self.coinstate.add_block(block, int(time())) # Originally there was a disk write in this spot. During testing of the chain.cache changes, # it was found there is a race condition between the mining thread and the networking thread. # Better to skip the write here and just let the networking thread do it. print(f"miner {miner_id} found block: {block_filename(block)}") # get new public key for miner self.public_key = self.wallet.get_annotated_public_key( "reserved for potentially mined block") save_wallet(self.wallet) self.balance = self.wallet.get_balance( self.coinstate) / Decimal(SASHIMI_PER_COIN)
def main(): parser = DefaultArgumentParser() args = parser.parse_args() configure_logging_from_args(args) create_chain_dir() coinstate = read_chain_from_disk() wallet = open_or_init_wallet() initialize_peers_file() thread = start_networking_peer_in_background(args, coinstate) thread.local_peer.show_stats() if check_for_fresh_chain(thread): thread.local_peer.show_stats() print("Starting mining: A repeat minter") try: print("Starting main loop") while True: public_key = wallet.get_annotated_public_key( "reserved for potentially mined block") save_wallet(wallet) nonce = random.randrange(1 << 32) last_round_second = int(time()) i = 0 while True: if int(time()) > last_round_second: print("Hashrate:", i) last_round_second = int(time()) i = 0 coinstate, transactions = thread.local_peer.chain_manager.get_state( ) increasing_time = max(int(time()), coinstate.head().timestamp + 1) block = construct_block_for_mining( coinstate, transactions, SECP256k1PublicKey(public_key), increasing_time, b'', nonce) i += 1 nonce = (nonce + 1) % (1 << 32) if block.hash() < block.target: break coinstate = coinstate.add_block(block, int(time())) with open(Path('chain') / block_filename(block), 'wb') as f: f.write(block.serialize()) print("FOUND", block_filename(block)) print("Wallet balance: %s skepticoin" % (wallet.get_balance(coinstate) / Decimal(SASHIMI_PER_COIN))) thread.local_peer.chain_manager.set_coinstate(coinstate) thread.local_peer.network_manager.broadcast_block(block) except KeyboardInterrupt: print("KeyboardInterrupt") finally: print("Stopping networking thread") thread.stop() print("Waiting for networking thread to stop") thread.join() print("Done; waiting for Python-exit")
def __call__(self) -> None: configure_logging_from_args(self.args) check_chain_dir() self.coinstate = read_chain_from_disk() self.wallet = open_or_init_wallet() self.start_balance = self.wallet.get_balance( self.coinstate) / Decimal(SASHIMI_PER_COIN) self.balance = self.start_balance self.network_thread = start_networking_peer_in_background( self.args, self.coinstate) self.network_thread.local_peer.show_stats() if check_for_fresh_chain(self.network_thread): self.network_thread.local_peer.show_stats() if self.network_thread.local_peer.chain_manager.coinstate.head( ).height <= MAX_KNOWN_HASH_HEIGHT: print("Your blockchain is not just old, it is ancient; ABORTING") exit(1) self.public_key = self.wallet.get_annotated_public_key( "reserved for potentially mined block") save_wallet(self.wallet) for miner_id in range(self.args.n): if miner_id > 0: self.args.dont_listen = True send_queue: Queue = Queue() process = Process(target=run_miner, daemon=True, args=(self.args, self.recv_queue, send_queue, miner_id)) process.start() self.processes.append(process) self.send_queues.append(send_queue) self.start_time = datetime.now() - timedelta( seconds=1) # prevent negative uptime due to second rounding try: while True: queue_item: Tuple[int, str, Any] = self.recv_queue.get() self.handle_received_message(queue_item) except KeyboardInterrupt: pass except Exception: print("Error in MinerWatcher message loop: " + traceback.format_exc()) finally: print("Restoring unused public key") self.wallet.restore_annotated_public_key( self.public_key, "reserved for potentially mined block") print("Stopping networking thread") self.network_thread.stop() print("Waiting for networking thread to stop") self.network_thread.join() for process in self.processes: process.join()
def main() -> None: parser = DefaultArgumentParser() parser.add_argument("amount", help="The amount of to send", type=int) parser.add_argument("denomination", help="'skepticoin' or 'sashimi'", choices=['skepticoin', 'sashimi']) parser.add_argument("address", help="The address to send to") args = parser.parse_args() configure_logging_from_args(args) value = args.amount * (SASHIMI_PER_COIN if args.denomination == 'skepticoin' else 1) if not is_valid_address(args.address): print("Invalid address") return check_chain_dir() coinstate = read_chain_from_disk() wallet = open_or_init_wallet() thread = start_networking_peer_in_background(args, coinstate) try: # we need a fresh chain because our wallet doesn't track spending/receiving, so we need to look at the real # blockchain to know what we can spend. check_for_fresh_chain(thread) print("Chain up to date") target_address = SECP256k1PublicKey(parse_address(args.address)) change_address = SECP256k1PublicKey(wallet.get_annotated_public_key("change")) save_wallet(wallet) transaction = create_spend_transaction( wallet, coinstate, value, 0, # we'll get to paying fees later target_address, change_address, ) validate_non_coinbase_transaction_by_itself(transaction) assert coinstate.current_chain_hash validate_non_coinbase_transaction_in_coinstate(transaction, coinstate.current_chain_hash, coinstate) print("Broadcasting transaction on the network", transaction) thread.local_peer.network_manager.broadcast_transaction(transaction) print("Monitoring...") while True: sleep(5) # it's late and I'm too lazy for the efficient & correct implementation. coinstate = thread.local_peer.chain_manager.coinstate max_height = coinstate.head().height for i in range(10): block = coinstate.by_height_at_head()[max(max_height - i, 0)] if transaction in block.transactions: print("Transaction confirmed at", block.height, "with", i, "confirmation blocks") if i == 6: # this is the magic number of confirmations according to the "literature" on the subject thread.stop() return except KeyboardInterrupt: print("KeyboardInterrupt") finally: print("Stopping networking thread") thread.stop() print("Waiting for networking thread to stop") thread.join() print("Done; waiting for Python-exit")
def main(): parser = DefaultArgumentParser() args = parser.parse_args() configure_logging_from_args(args) create_chain_dir() coinstate = read_chain_from_disk() wallet = open_or_init_wallet() initialize_peers_file() thread = start_networking_peer_in_background(args, coinstate) thread.local_peer.show_stats() if check_for_fresh_chain(thread): thread.local_peer.show_stats() if thread.local_peer.chain_manager.coinstate.head().height <= MAX_KNOWN_HASH_HEIGHT: print("Your blockchain is not just old, it is ancient; ABORTING") return start_time = datetime.now() start_balance = wallet.get_balance(coinstate) / Decimal(SASHIMI_PER_COIN) balance = start_balance print("Wallet balance: %s skepticoin" % start_balance) print("Starting mining: A repeat minter") try: print("Starting main loop") while True: public_key = wallet.get_annotated_public_key("reserved for potentially mined block") save_wallet(wallet) nonce = random.randrange(1 << 32) last_round_second = int(time()) hashes = 0 while True: if int(time()) > last_round_second: now = datetime.now() now_str = now.strftime("%Y-%m-%d %H:%M:%S") uptime = now - start_time uptime_str = str(uptime).split(".")[0] mined = balance - start_balance mine_speed = (float(mined) / uptime.total_seconds()) * 60 * 60 print(f"{now_str} | uptime: {uptime_str} | {hashes:>2} hash/sec" + f" | mined: {mined:>3} SKEPTI | {mine_speed:5.2f} SKEPTI/h") last_round_second = int(time()) hashes = 0 coinstate, transactions = thread.local_peer.chain_manager.get_state() increasing_time = max(int(time()), coinstate.head().timestamp + 1) block = construct_block_for_mining( coinstate, transactions, SECP256k1PublicKey(public_key), increasing_time, b'', nonce) hashes += 1 nonce = (nonce + 1) % (1 << 32) if block.hash() < block.target: break coinstate = coinstate.add_block(block, int(time())) with open(Path('chain') / block_filename(block), 'wb') as f: f.write(block.serialize()) print("FOUND", block_filename(block)) balance = (wallet.get_balance(coinstate) / Decimal(SASHIMI_PER_COIN)) print("Wallet balance: %s skepticoin" % balance) thread.local_peer.chain_manager.set_coinstate(coinstate) thread.local_peer.network_manager.broadcast_block(block) except KeyboardInterrupt: print("KeyboardInterrupt") finally: print("Stopping networking thread") thread.stop() print("Waiting for networking thread to stop") thread.join() print("Done; waiting for Python-exit")