예제 #1
0
 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
예제 #2
0
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
예제 #3
0
    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)
예제 #4
0
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")
예제 #5
0
    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()
예제 #6
0
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")
예제 #7
0
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")