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()));
}
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);
}
}
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);
}
}
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);
}
}
}
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());
}
}
Aggregations