Search in sources :

Example 1 with AtomicFileOutputStream

use of duckutil.AtomicFileOutputStream in project snowblossom by snowblossomcoin.

the class WalletUtil method saveWallet.

public static void saveWallet(WalletDatabase db, File wallet_path) throws Exception {
    wallet_path.mkdirs();
    Random rnd = new Random();
    byte[] rnd_data = new byte[7];
    rnd.nextBytes(rnd_data);
    String name = "snow-" + db.getVersion() + "_" + HexUtil.getHexString(rnd_data) + ".wallet";
    File db_file = new File(wallet_path, name);
    if (db_file.exists()) {
        throw new RuntimeException("SOMETHING VERY UNLIKELY HAS OCCURED. ABORTING SAVE.");
    }
    AtomicFileOutputStream out = new AtomicFileOutputStream(db_file);
    db.writeTo(out);
    out.flush();
    out.close();
    {
        // Write readme file
        File readme_file = new File(wallet_path, "readme.txt");
        FileOutputStream readme_out = new FileOutputStream(readme_file);
        PrintStream readme_print = new PrintStream(readme_out);
        readme_print.println("This directory contains a Snowblossom Wallet.");
        readme_print.println("");
        readme_print.println("If backing this up, save the entire directory including all .wallet files in it.");
        readme_print.println("It is safe to access a wallet directory from multiple clients on the same computer");
        readme_print.println("or on multiple computers with real-time or eventual synchronization.");
        readme_print.println("");
        readme_print.println("Wallet data safety is ensured by the snowblossom client always writing the wallet");
        readme_print.println("out to a new file with a random file name and only then deleting the old file(s).");
        readme_print.println("This way, if multiple clients are making changes there will simple be multiple files.");
        readme_print.println("The next client to update the wallet will merge those and make a new single file.");
        readme_print.println("");
        readme_print.println("In addition, each file has a proto version.  If a client sees a higher version it will");
        readme_print.println("assume there are new fields that it does not know how to correctly merge and won't remove");
        readme_print.println("the higher versioned files.  So it will always be safe to open a wallet with an older");
        readme_print.println("snowblossom client.");
        readme_print.flush();
        readme_out.close();
    }
    logger.log(Level.FINE, String.format("Save to file %s completed", db_file.getPath()));
}
Also used : PrintStream(java.io.PrintStream) AtomicFileOutputStream(duckutil.AtomicFileOutputStream) Random(java.util.Random) AtomicFileOutputStream(duckutil.AtomicFileOutputStream) FileOutputStream(java.io.FileOutputStream) ByteString(com.google.protobuf.ByteString) File(java.io.File)

Example 2 with AtomicFileOutputStream

use of duckutil.AtomicFileOutputStream in project snowblossom by snowblossomcoin.

the class AtomicFileMap method put.

@Override
public void put(ByteString key, ByteString value) {
    base.mkdirs();
    File f = getFileForKey(key);
    try {
        AtomicFileOutputStream a_out = new AtomicFileOutputStream(f);
        a_out.write(value.toByteArray());
        a_out.flush();
        a_out.close();
    } catch (java.io.IOException e) {
        System.out.println("Writing to: " + f);
        throw new RuntimeException(e);
    }
}
Also used : AtomicFileOutputStream(duckutil.AtomicFileOutputStream) File(java.io.File)

Example 3 with AtomicFileOutputStream

use of duckutil.AtomicFileOutputStream in project snowblossom by snowblossomcoin.

the class AtomicFileMapSet method add.

@Override
public void add(ByteString key, ByteString value) {
    try {
        File f = getFileForKeyValue(key, value);
        f.getParentFile().mkdirs();
        AtomicFileOutputStream f_out = new AtomicFileOutputStream(f);
        f_out.write(value.toByteArray());
        f_out.flush();
        f_out.close();
    } catch (java.io.IOException e) {
        throw new RuntimeException(e);
    }
}
Also used : AtomicFileOutputStream(duckutil.AtomicFileOutputStream) File(java.io.File)

Example 4 with AtomicFileOutputStream

use of duckutil.AtomicFileOutputStream in project snowblossom by snowblossomcoin.

the class SnowBlossomClient method main.

public static void main(String[] args) throws Exception {
    Globals.addCryptoProvider();
    if (args.length < 1) {
        logger.log(Level.SEVERE, "Incorrect syntax. Syntax: SnowBlossomClient <config_file> [commands]");
        System.exit(-1);
    }
    ConfigFile config = new ConfigFile(args[0], "snowblossom_");
    config.require("wallet_path");
    LogSetup.setup(config);
    SnowBlossomClient client = null;
    if ((args.length == 2) && (args[1].equals("import_seed"))) {
        System.out.println("Please enter seed to import:");
        Scanner scan = new Scanner(System.in);
        String seed = scan.nextLine().trim();
        SeedUtil.checkSeed(seed);
        client = new SnowBlossomClient(config, seed);
    } else {
        client = new SnowBlossomClient(config);
    }
    if (args.length == 1) {
        client.maintainKeys();
        client.showBalances(false);
        WalletUtil.printBasicStats(client.getPurse().getDB());
        System.out.println("Here is an unused address:");
        AddressSpecHash hash = client.getPurse().getUnusedAddress(false, false);
        String addr = AddressUtil.getAddressString(client.getParams().getAddressPrefix(), hash);
        System.out.println(addr);
    }
    if (args.length > 1) {
        String command = args[1];
        client.maintainKeys();
        if (command.equals("send")) {
            if (args.length < 4) {
                logger.log(Level.SEVERE, "Incorrect syntax. Syntax: SnowBlossomClient <config_file> send <amount> <dest_address>");
                System.exit(-1);
            }
            boolean send_all = false;
            String val_str = args[2];
            long value = 0L;
            double val_snow = 0.0;
            if (val_str.equals("all")) {
                send_all = true;
            } else {
                val_snow = Double.parseDouble(args[2]);
                value = (long) (val_snow * Globals.SNOW_VALUE);
            }
            String to = args[3];
            DecimalFormat df = new DecimalFormat("0.000000");
            if (send_all) {
                logger.info(String.format("Building send of ALL to %s", to));
            } else {
                logger.info(String.format("Building send of %s to %s", df.format(val_snow), to));
            }
            client.send(value, to, send_all);
        } else if (command.equals("sendlocked")) {
            client.maintainKeys();
            if (args.length < 6) {
                logger.log(Level.SEVERE, "Incorrect syntax. Syntax: SnowBlossomClient <config_file> sendlocked <amount> <dest_address> <fbo_address> <block> [name_type] [name]");
                System.exit(-1);
            }
            double val_snow = Double.parseDouble(args[2]);
            long value = (long) (val_snow * Globals.SNOW_VALUE);
            String to = args[3];
            String fbo = args[4];
            int block = Integer.parseInt(args[5]);
            String name = null;
            String nametype = null;
            if (args.length > 7) {
                nametype = args[6];
                name = args[7];
            }
            DecimalFormat df = new DecimalFormat("0.000000");
            logger.info(String.format("Building locked send of %s to %s for %s until %d", df.format(val_snow), to, fbo, block));
            client.sendLocked(value, to, fbo, block, nametype, name);
        } else if (command.equals("balance")) {
            client.maintainKeys();
            client.showBalances(true);
        } else if (command.equals("getfresh")) {
            client.getPurse().maintainKeys(false);
            boolean mark_used = false;
            boolean generate_now = false;
            if (args.length > 2) {
                mark_used = Boolean.parseBoolean(args[2]);
            }
            if (args.length > 3) {
                generate_now = Boolean.parseBoolean(args[3]);
            }
            AddressSpecHash hash = client.getPurse().getUnusedAddress(mark_used, generate_now);
            String addr = AddressUtil.getAddressString(client.getParams().getAddressPrefix(), hash);
            System.out.println(addr);
        } else if (command.equals("monitor")) {
            BalanceInfo bi_last = null;
            MonitorTool mu = new MonitorTool(client.getParams(), client.getStubHolder(), new MonitorInterfaceSystemOut());
            for (AddressSpec claim : client.getPurse().getDB().getAddressesList()) {
                AddressSpecHash hash = AddressUtil.getHashForSpec(claim);
                mu.addAddress(hash);
            }
            while (true) {
                try {
                    if (client == null) {
                        client = new SnowBlossomClient(config);
                    }
                    BalanceInfo bi = client.getBalance();
                    if (!bi.equals(bi_last)) {
                        System.out.println("Total: " + getBalanceInfoPrint(bi));
                        bi_last = bi;
                    }
                } catch (Throwable t) {
                    t.printStackTrace();
                    client = null;
                }
                Thread.sleep(10000);
            }
        } else if (command.equals("rpcserver")) {
            client.maintainKeys();
            JsonRpcServer json_server = new JsonRpcServer(config, true);
            RpcServerHandler server_handler = new RpcServerHandler(client);
            server_handler.registerHandlers(json_server);
            new RpcUtil(client.getParams()).registerHandlers(json_server);
            logger.info("RPC Server started");
            while (true) {
                Thread.sleep(1000);
            }
        } else if (command.equals("export")) {
            if (args.length != 3) {
                logger.log(Level.SEVERE, "export must be followed by filename to write to");
                System.exit(-1);
            }
            JsonFormat.Printer printer = JsonFormat.printer();
            AtomicFileOutputStream atomic_out = new AtomicFileOutputStream(args[2]);
            PrintStream print_out = new PrintStream(atomic_out);
            print_out.println(printer.print(client.getPurse().getDB()));
            print_out.close();
            logger.info(String.format("Wallet saved to %s", args[2]));
        } else if (command.equals("export_watch_only")) {
            if (args.length != 3) {
                logger.log(Level.SEVERE, "export must be followed by filename to write to");
                System.exit(-1);
            }
            JsonFormat.Printer printer = JsonFormat.printer();
            AtomicFileOutputStream atomic_out = new AtomicFileOutputStream(args[2]);
            PrintStream print_out = new PrintStream(atomic_out);
            WalletDatabase watch_db = WalletUtil.getWatchCopy(client.getPurse().getDB());
            print_out.println(printer.print(watch_db));
            print_out.close();
            logger.info(String.format("Wallet saved to %s", args[2]));
        } else if (command.equals("import")) {
            JsonFormat.Parser parser = JsonFormat.parser();
            WalletDatabase.Builder wallet_import = WalletDatabase.newBuilder();
            if (args.length != 3) {
                logger.log(Level.SEVERE, "import must be followed by filename to read from");
                System.exit(-1);
            }
            Reader input = new InputStreamReader(new FileInputStream(args[2]));
            parser.merge(input, wallet_import);
            if (config.getBoolean("watch_only") && (wallet_import.getKeysCount() > 0)) {
                logger.log(Level.SEVERE, "Attempting to import wallet with keys into watch only wallet. Nope.");
                System.exit(-1);
            }
            WalletUtil.testWallet(wallet_import.build());
            client.getPurse().mergeIn(wallet_import.build());
            logger.info("Imported data:");
            WalletUtil.printBasicStats(wallet_import.build());
        } else if (command.equals("import_xpub")) {
            if (args.length != 3) {
                logger.log(Level.SEVERE, "import_xpub must be followed by xpub to import");
                System.exit(-1);
            }
            WalletDatabase wallet_import = WalletUtil.importXpub(client.getParams(), args[2]);
            client.getPurse().mergeIn(wallet_import);
            client.getPurse().maintainKeys(false);
        } else if (command.equals("import_seed")) {
            if (args.length != 2) {
                logger.log(Level.SEVERE, "No options allowed for import_seed");
                System.exit(-1);
            }
            client.getPurse().maintainKeys(true);
        } else if (command.equals("loadtest")) {
            // client.maintainKeys();
            new LoadTest(client).runLoadTest();
        } else if (command.equals("loadtest_shard")) {
            // client.maintainKeys();
            new LoadTestShard(client).runLoadTest();
        } else if (command.equals("nodestatus")) {
            NodeStatus ns = client.getNodeStatus();
            JsonFormat.Printer printer = JsonFormat.printer();
            System.out.println(printer.print(ns));
        } else if (command.equals("show_seed")) {
            WalletDatabase db = client.getPurse().getDB();
            SeedReport sr = WalletUtil.getSeedReport(db);
            for (Map.Entry<String, String> seed : sr.seeds.entrySet()) {
                System.out.println("Public: " + seed.getValue());
                System.out.println("Seed: " + seed.getKey());
            }
            for (String xpub : sr.watch_xpubs) {
                System.out.println("Watch-only xpub: " + xpub);
            }
            if (sr.watch_xpubs.size() == 0) {
                if (sr.missing_keys > 0) {
                    System.out.println(String.format("WARNING: THIS WALLET CONTAINS %d KEYS THAT DO NOT COME FROM SEEDS.  THIS WALLET CAN NOT BE COMPLETELY RESTORED FROM SEEDS", sr.missing_keys));
                } else {
                    System.out.println("All keys in this wallet are derived from the seed(s) above and will be recoverable from those seeds.");
                }
            }
        } else if (command.equals("audit_log_init")) {
            if (args.length != 3) {
                System.out.println("Syntax: audit_log_init <msg>");
                System.exit(-1);
            }
            String msg = args[2];
            System.out.println(AuditLog.init(client, msg));
        } else if (command.equals("audit_log_record")) {
            if (args.length != 3) {
                System.out.println("Syntax: audit_log_record <msg>");
                System.exit(-1);
            }
            String msg = args[2];
            System.out.println(AuditLog.recordLog(client, msg));
        } else if (command.equals("audit_log_report")) {
            if (args.length != 3) {
                System.out.println("Syntax: audit_log_report <address>");
                System.exit(-1);
            }
            AddressSpecHash audit_log_hash = AddressUtil.getHashForAddress(client.getParams().getAddressPrefix(), args[2]);
            AuditLogReport report = AuditLog.getAuditReport(client, audit_log_hash);
            System.out.println(report);
        } else {
            logger.log(Level.SEVERE, String.format("Unknown command %s.", command));
            System.out.println("Commands:");
            System.out.println("(no command) - show total balance, show one fresh address");
            System.out.println("  balance - show balance of all addresses");
            System.out.println("  monitor - show balance and repeat");
            System.out.println("  getfresh [mark_used] [generate_now] - get a fresh address");
            System.out.println("    if mark_used is true, mark the address as used");
            System.out.println("    if generate_now is true, generate a new address rather than using the key pool");
            System.out.println("  send <amount> <destination> - send snow to address");
            System.out.println("  export <file> - export wallet to json file");
            System.out.println("  export_watch_only <file> - export wallet to json file with no keys");
            System.out.println("  import <file> - import wallet from json file, merges with existing");
            System.out.println("  import_seed - prompts for a seed to import");
            System.out.println("  import_xpub - imports a given xpub to watch");
            System.out.println("  show_seed - show seeds");
            System.out.println("  rpcserver - run a local rpc server for client commands");
            System.out.println("  audit_log_init <msg> - initialize a new audit log chain");
            System.out.println("  audit_log_record <msg> - record next audit log in chain");
            System.out.println("  audit_log_report <address> - get a report of audit log on address");
            System.out.println("  sendlocked <amount> <dest_address> <fbo_address> <block> [name_type] [name]");
            System.exit(-1);
        }
    }
}
Also used : AtomicFileOutputStream(duckutil.AtomicFileOutputStream) DecimalFormat(java.text.DecimalFormat) Reader(java.io.Reader) InputStreamReader(java.io.InputStreamReader) ByteString(com.google.protobuf.ByteString) JsonFormat(com.google.protobuf.util.JsonFormat) PrintStream(java.io.PrintStream) JsonRpcServer(duckutil.jsonrpc.JsonRpcServer) InputStreamReader(java.io.InputStreamReader) ConfigFile(duckutil.ConfigFile) FileInputStream(java.io.FileInputStream)

Example 5 with AtomicFileOutputStream

use of duckutil.AtomicFileOutputStream in project snowblossom by snowblossomcoin.

the class ReportManager method writeReport.

public synchronized void writeReport(String path) {
    try {
        PrintStream out = new PrintStream(new AtomicFileOutputStream(path));
        DecimalFormat df = new DecimalFormat("0.0");
        out.println("Total: " + total.getReportLong(df));
        TreeSet<String> to_remove = new TreeSet<>();
        for (Map.Entry<String, RateReporter> me : rate_map.entrySet()) {
            if (me.getValue().isZero()) {
                to_remove.add(me.getKey());
            } else {
                out.println(me.getKey() + " " + me.getValue().getReportLong(df));
            }
        }
        for (String k : to_remove) {
            rate_map.remove(k);
        }
        out.flush();
        out.close();
    } catch (Exception e) {
        logger.log(Level.WARNING, "Error writing report: " + e.toString());
    }
}
Also used : PrintStream(java.io.PrintStream) AtomicFileOutputStream(duckutil.AtomicFileOutputStream) TreeSet(java.util.TreeSet) DecimalFormat(java.text.DecimalFormat) TreeMap(java.util.TreeMap) Map(java.util.Map) RateReporter(duckutil.RateReporter)

Aggregations

AtomicFileOutputStream (duckutil.AtomicFileOutputStream)5 File (java.io.File)3 PrintStream (java.io.PrintStream)3 ByteString (com.google.protobuf.ByteString)2 DecimalFormat (java.text.DecimalFormat)2 JsonFormat (com.google.protobuf.util.JsonFormat)1 ConfigFile (duckutil.ConfigFile)1 RateReporter (duckutil.RateReporter)1 JsonRpcServer (duckutil.jsonrpc.JsonRpcServer)1 FileInputStream (java.io.FileInputStream)1 FileOutputStream (java.io.FileOutputStream)1 InputStreamReader (java.io.InputStreamReader)1 Reader (java.io.Reader)1 Map (java.util.Map)1 Random (java.util.Random)1 TreeMap (java.util.TreeMap)1 TreeSet (java.util.TreeSet)1