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 }