github.com/piotrnar/gocoin@v0.0.0-20240512203912-faa0448c5e96/wallet/main.go (about)

     1  package main
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"os"
     7  
     8  	"github.com/piotrnar/gocoin"
     9  	"github.com/piotrnar/gocoin/lib/btc"
    10  	"github.com/piotrnar/gocoin/lib/others/sys"
    11  )
    12  
    13  var (
    14  	PassSeedFilename = ".secret"
    15  	RawKeysFilename  = ".others"
    16  )
    17  
    18  var (
    19  	// Command line switches
    20  	cfg_fn *string = flag.String("cfg", "wallet.cfg", "Specify name of the config file (overwrites env's GOCOIN_WALLET_CONFIG)")
    21  
    22  	// Wallet options
    23  	list      *bool = flag.Bool("l", false, "List public (deposit) addressses and save them to wallet.txt file")
    24  	singleask *bool = flag.Bool("1", false, "Do not re-ask for the password (when used along with -l)")
    25  	noverify  *bool = flag.Bool("q", false, "Do not double check keys while listing them (use with -l)")
    26  	verbose   *bool = flag.Bool("v", false, "Verbose version (print more info)")
    27  	ask4pass  *bool = flag.Bool("p", false, "Force the wallet to ask for seed password (ignore .secret file)")
    28  	nosseed   *bool = flag.Bool("is", false, "Ignore the seed paremeter from the config file")
    29  	subfee    *bool = flag.Bool("f", false, "Substract fee from the first value")
    30  
    31  	dumppriv *string = flag.String("dump", "", "Export a private key of a given deposit address (use * for all)")
    32  
    33  	// Spending money options
    34  	send   *string = flag.String("send", "", "Send money as defined by the list of pairs: address1=amount1[,address2=amount2]")
    35  	batch  *string = flag.String("batch", "", "Send money as defined by the content of the given file (each line: address=amount)")
    36  	change *string = flag.String("change", "", "Send any change to this address (otherwise return it to the 1st input)")
    37  
    38  	// Message signing options
    39  	signaddr *string = flag.String("sign", "", "Perform sign operation with the given P2KH address (use with -msg or -hash)")
    40  	message  *string = flag.String("msg", "", "Specify text message to be signed or added as transaction's extra OP_RETURN output")
    41  
    42  	useallinputs *bool = flag.Bool("useallinputs", false, "Use all the current balance's unspent outputs as the transaction inputs")
    43  
    44  	// Sign raw TX
    45  	rawtx *string = flag.String("raw", "", "Sign a raw transaction (specify filename as the parameter)")
    46  
    47  	// Decode raw tx
    48  	dumptxfn *string = flag.String("d", "", "Decode a raw transaction (specify filename as the parameter)")
    49  
    50  	// Sign raw message
    51  	signhash *string = flag.String("hash", "", "Sign a raw hash value (use together with -sign parameter)")
    52  
    53  	// Print a public key of a give bitcoin address
    54  	pubkey *string = flag.String("pub", "", "Print the public key of the given deposit address")
    55  
    56  	// Print a public key of a give bitcoin address
    57  	p2sh             *string = flag.String("p2sh", "", "Insert given P2SH script into the transaction (use with -raw and optionally -input)")
    58  	input            *int    = flag.Int("input", -1, "Insert P2SH script only at this input number (use with -p2sh)")
    59  	multisign        *string = flag.String("msign", "", "Sign multisig transaction with given bitcoin address (use with -raw)")
    60  	allowextramsigns *bool   = flag.Bool("xtramsigs", false, "Allow to put more signatures than needed (for multisig txs)")
    61  
    62  	sequence *int = flag.Int("seq", 0, "Use given Replace-By-Fee sequence number (-1 or -2 for final)")
    63  
    64  	dumpxprv  *bool = flag.Bool("xprv", false, "Print BIP32 Extrened Private Key (use with type=4)")
    65  	dumpwords *bool = flag.Bool("words", false, "Print BIP39 mnemonic (use with type=4)")
    66  
    67  	encrypt *string = flag.String("encrypt", "", "Encrypt this file using the wallet's seed password")
    68  	decrypt *string = flag.String("decrypt", "", "Decrypt this file using the wallet's seed password")
    69  )
    70  
    71  // cleanExit exits after cleaning up private data from memory.
    72  func cleanExit(code int) {
    73  	if *verbose {
    74  		fmt.Println("Cleaning up private keys")
    75  	}
    76  	for k := range keys {
    77  		sys.ClearBuffer(keys[k].Key)
    78  	}
    79  	os.Exit(code)
    80  }
    81  
    82  func main() {
    83  	// Print the logo to stderr
    84  	println("Gocoin Wallet version", gocoin.Version)
    85  	println("This program comes with ABSOLUTELY NO WARRANTY")
    86  	println()
    87  
    88  	flag.BoolVar(list, "list", false, "Same as -l (above)")
    89  
    90  	parse_config()
    91  
    92  	flag.Parse() // this one prints defaults and exits in case of unknown switches or when help requested
    93  
    94  	if uncompressed {
    95  		println("For SegWit address safety, uncompressed keys are disabled in this version")
    96  		os.Exit(1)
    97  	}
    98  
    99  	if usescrypt > 30 {
   100  		println("ERROR: scrypt value too big")
   101  		os.Exit(1)
   102  	}
   103  
   104  	check_atype()
   105  
   106  	// convert string fee to uint64
   107  	if val, e := btc.StringToSatoshis(fee); e != nil {
   108  		println("Incorrect fee value", fee)
   109  		os.Exit(1)
   110  	} else {
   111  		curFee = val
   112  	}
   113  
   114  	// decode raw transaction?
   115  	if *dumptxfn != "" {
   116  		dump_raw_tx()
   117  		return
   118  	}
   119  
   120  	// dump public key or secret scan key?
   121  	if *pubkey != "" {
   122  		make_wallet()
   123  		cleanExit(0)
   124  	}
   125  
   126  	// list public addresses?
   127  	if *list {
   128  		make_wallet()
   129  		dump_addrs()
   130  		cleanExit(0)
   131  	}
   132  
   133  	// dump privete key?
   134  	if *dumppriv != "" {
   135  		make_wallet()
   136  		dump_prvkey()
   137  		cleanExit(0)
   138  	}
   139  
   140  	// sign a message or a hash?
   141  	if *signaddr != "" {
   142  		make_wallet()
   143  		sign_message()
   144  		if *send == "" {
   145  			// Don't load_balance if he did not want to spend coins as well
   146  			cleanExit(0)
   147  		}
   148  	}
   149  
   150  	// raw transaction?
   151  	if *rawtx != "" {
   152  		// add p2sh sript to it?
   153  		if *p2sh != "" {
   154  			make_p2sh()
   155  			cleanExit(0)
   156  		}
   157  
   158  		make_wallet()
   159  
   160  		// multisig sign with a specific key?
   161  		if *multisign != "" {
   162  			multisig_sign()
   163  			cleanExit(0)
   164  		}
   165  
   166  		// this must be signing of a raw trasnaction
   167  		load_balance()
   168  		process_raw_tx()
   169  		cleanExit(0)
   170  	}
   171  
   172  	// make the wallet nad print balance
   173  	make_wallet()
   174  	if e := load_balance(); e != nil {
   175  		fmt.Println("ERROR:", e.Error())
   176  		fmt.Println("Failed to load wallet's balance data. Execute 'wallet -h' for help.")
   177  		cleanExit(1)
   178  	}
   179  
   180  	// send command?
   181  	if send_request() {
   182  		make_signed_tx()
   183  		cleanExit(0)
   184  	}
   185  
   186  	show_balance()
   187  	cleanExit(0)
   188  }