func p_snd(w http.ResponseWriter, r *http.Request) { if !ipchecker(r) { return } s := load_template("send.html") wallet.BalanceMutex.Lock() if wallet.MyWallet != nil && len(wallet.MyBalance) > 0 { wal := load_template("send_wal.html") row_tmp := load_template("send_wal_row.html") wal = strings.Replace(wal, "{TOTAL_BTC}", fmt.Sprintf("%.8f", float64(wallet.LastBalance)/1e8), 1) wal = strings.Replace(wal, "{UNSPENT_OUTS}", fmt.Sprint(len(wallet.MyBalance)), -1) for i := range wallet.MyBalance { row := row_tmp row = strings.Replace(row, "{WALLET_FILE}", html.EscapeString(wallet.MyBalance[i].BtcAddr.Extra.Wallet), 1) lab := wallet.MyBalance[i].BtcAddr.Extra.Label if wallet.MyBalance[i].BtcAddr.Extra.Virgin { lab += " ***" } var estimated_sig_size uint ms, msr := wallet.IsMultisig(wallet.MyBalance[i].BtcAddr) if ms { if msr != nil { estimated_sig_size = msr.KeysRequired*AvgSignatureSize + msr.KeysProvided*AvgPublicKeySize } else { estimated_sig_size = 2*AvgSignatureSize + 3*AvgPublicKeySize } } else { estimated_sig_size = AvgSignatureSize + AvgPublicKeySize } row = strings.Replace(row, "{ADDR_LABEL}", html.EscapeString(lab), 1) row = strings.Replace(row, "{ROW_NUMBER}", fmt.Sprint(i+1), -1) row = strings.Replace(row, "{MINED_IN}", fmt.Sprint(wallet.MyBalance[i].MinedAt), 1) row = strings.Replace(row, "{TX_ID}", btc.NewUint256(wallet.MyBalance[i].TxPrevOut.Hash[:]).String(), -1) row = strings.Replace(row, "{TX_VOUT}", fmt.Sprint(wallet.MyBalance[i].TxPrevOut.Vout), -1) row = strings.Replace(row, "{TX_SIGSIZ}", fmt.Sprint(estimated_sig_size), -1) row = strings.Replace(row, "{BTC_AMOUNT}", fmt.Sprintf("%.8f", float64(wallet.MyBalance[i].Value)/1e8), 1) row = strings.Replace(row, "{OUT_VALUE}", fmt.Sprint(wallet.MyBalance[i].Value), 1) row = strings.Replace(row, "{BTC_ADDR}", wallet.MyBalance[i].DestAddr(), 1) row = strings.Replace(row, "<!--BTC_ADDR_TITLE-->", wallet.MyBalance[i].BtcAddr.String(), 1) wal = templ_add(wal, "<!--UTXOROW-->", row) } // Own wallet for i := range wallet.MyWallet.Addrs { row := "wallet.push({'addr':'" + wallet.MyWallet.Addrs[i].Enc58str + "', " + "'label':'" + wallet.MyWallet.Addrs[i].Extra.Label + "', " + "'wallet':'" + wallet.MyWallet.Addrs[i].Extra.Wallet + "', " + "'virgin':" + fmt.Sprint(wallet.MyWallet.Addrs[i].Extra.Virgin) + "})\n" wal = templ_add(wal, "/*WALLET_ENTRY_JS*/", row) } wal = strings.Replace(wal, "/*WALLET_ENTRY_JS*/", "const ADDR_LIST_SIZE = "+fmt.Sprint(common.CFG.WebUI.AddrListLen), 1) s = strings.Replace(s, "<!--WALLET-->", wal, 1) } else { if wallet.MyWallet == nil { s = strings.Replace(s, "<!--WALLET-->", "You have no wallet", 1) } else { s = strings.Replace(s, "<!--WALLET-->", "Your current wallet is empty", 1) } } wallet.BalanceMutex.Unlock() write_html_head(w, r) w.Write([]byte(s)) write_html_tail(w) }
func p_wal(w http.ResponseWriter, r *http.Request) { if !ipchecker(r) { return } if checksid(r) { if len(r.Form["wal"]) > 0 { wallet.LoadWallet(common.GocoinHomeDir + "wallet" + string(os.PathSeparator) + r.Form["wal"][0]) http.Redirect(w, r, "/wal", http.StatusFound) return } if len(r.Form["setunused"]) > 0 { i, er := strconv.ParseUint(r.Form["setunused"][0], 10, 32) if er == nil && int(i) < len(wallet.MyWallet.Addrs) { if wallet.MoveToUnused(wallet.MyWallet.Addrs[i].Enc58str, wallet.MyWallet.Addrs[i].Extra.Wallet) { wallet.LoadWallet(wallet.MyWallet.FileName) } } http.Redirect(w, r, "/wal", http.StatusFound) return } if len(r.Form["setlabel"]) > 0 && len(r.Form["lab"]) > 0 { i, er := strconv.ParseUint(r.Form["setlabel"][0], 10, 32) if er == nil && int(i) < len(wallet.MyWallet.Addrs) { if wallet.SetLabel(int(i), r.Form["lab"][0]) { wallet.LoadWallet(wallet.MyWallet.FileName) } } http.Redirect(w, r, "/wal", http.StatusFound) return } } page := load_template("wallet.html") wal1 := load_template("wallet_qsw.html") addr := load_template("wallet_adr.html") page = strings.Replace(page, "{TOTAL_BTC}", fmt.Sprintf("%.8f", float64(wallet.LastBalance)/1e8), 1) page = strings.Replace(page, "{UNSPENT_OUTS}", fmt.Sprint(len(wallet.MyBalance)), 1) fis, er := ioutil.ReadDir(common.GocoinHomeDir + "wallet/") if er == nil { for i := range fis { if !fis[i].IsDir() && fis[i].Size() > 1 && fis[i].Name()[0] != '.' { s := strings.Replace(wal1, "{WALLET_NAME}", fis[i].Name(), -1) page = templ_add(page, "<!--ONEWALLET-->", s) } } } wallet.BalanceMutex.Lock() if wallet.MyWallet != nil { page = strings.Replace(page, "<!--WALLET_FILENAME-->", wallet.MyWallet.FileName, 1) wc, er := ioutil.ReadFile(wallet.MyWallet.FileName) if er == nil { page = strings.Replace(page, "{WALLET_DATA}", string(wc), 1) } for i := range wallet.MyWallet.Addrs { ad := addr lab := wallet.MyWallet.Addrs[i].Extra.Label if wallet.MyWallet.Addrs[i].Extra.Virgin { lab += " ***" } ad = strings.Replace(ad, "<!--WAL_ROW_IDX-->", fmt.Sprint(i), -1) ad = strings.Replace(ad, "<!--WAL_ADDR-->", wallet.MyWallet.Addrs[i].Enc58str, 1) if len(wallet.MyWallet.Addrs[i].Enc58str) > 80 { ad = strings.Replace(ad, "<!--WAL_ADDR_STYLE-->", "addr_long", 1) } else { ad = strings.Replace(ad, "<!--WAL_ADDR_STYLE-->", "addr_norm", 1) } ad = strings.Replace(ad, "<!--WAL_WALLET-->", html.EscapeString(wallet.MyWallet.Addrs[i].Extra.Wallet), 1) ad = strings.Replace(ad, "<!--WAL_LABEL-->", html.EscapeString(lab), 1) ms, msr := wallet.IsMultisig(wallet.MyWallet.Addrs[i]) if ms { if msr != nil { ad = strings.Replace(ad, "<!--WAL_MULTISIG-->", fmt.Sprintf("%d of %d", msr.KeysRequired, msr.KeysProvided), 1) } else { ad = strings.Replace(ad, "<!--WAL_MULTISIG-->", "Yes", 1) } } else { ad = strings.Replace(ad, "<!--WAL_MULTISIG-->", "No", 1) } rec := wallet.CachedAddrs[wallet.MyWallet.Addrs[i].Hash160] if rec == nil { ad = strings.Replace(ad, "<!--WAL_BALANCE-->", "?", 1) ad = strings.Replace(ad, "<!--WAL_OUTCNT-->", "?", 1) page = templ_add(page, "<!--ONE_WALLET_ADDR-->", ad) continue } if !rec.InWallet { ad = strings.Replace(ad, "<!--WAL_BALANCE-->", "WTF", 1) ad = strings.Replace(ad, "<!--WAL_OUTCNT-->", "-2", 1) page = templ_add(page, "<!--ONE_WALLET_ADDR-->", ad) continue } ucu := wallet.CacheUnspent[rec.CacheIndex] if ucu == nil { ad = strings.Replace(ad, "<!--WAL_BALANCE-->", "WTF", 1) ad = strings.Replace(ad, "<!--WAL_OUTCNT-->", "-3", 1) page = templ_add(page, "<!--ONE_WALLET_ADDR-->", ad) continue } if len(ucu.AllUnspentTx) > 0 { ad = strings.Replace(ad, "<!--WAL_BALANCE-->", fmt.Sprintf("%.8f", float64(rec.Value)/1e8), 1) ad = strings.Replace(ad, "<!--WAL_OUTCNT-->", fmt.Sprint(len(ucu.AllUnspentTx)), 1) } else if wallet.MyWallet.Addrs[i].Extra.Virgin { // Do not display virgin addresses with zero balance continue } else if wallet.MyWallet.Addrs[i].Extra.Wallet != wallet.UnusedFileName && wallet.MyWallet.Addrs[i].Extra.Wallet != wallet.AddrBookFileName { ad = strings.Replace(ad, "<!--WAL_OUTCNT-->", fmt.Sprint("<a href=\"javascript:setunused(", i, ")\" title=\"Move to "+ wallet.UnusedFileName+"\"><img src=\"webui/del.png\"></a>"), 1) } page = templ_add(page, "<!--ONE_WALLET_ADDR-->", ad) } page = strings.Replace(page, "{WALLET_NAME}", filepath.Base(wallet.MyWallet.FileName), 1) } else { strings.Replace(page, "<!--WALLET_FILENAME-->", "<i>no wallet loaded</i>", 1) page = strings.Replace(page, "{WALLET_NAME}", "", -1) } wallet.BalanceMutex.Unlock() write_html_head(w, r) w.Write([]byte(page)) write_html_tail(w) }
func dl_payment(w http.ResponseWriter, r *http.Request) { if !ipchecker(r) { return } var err string if len(r.Form["outcnt"]) == 1 { var thisbal chain.AllUnspentTx var pay_cmd string var totalinput, spentsofar uint64 var change_addr *btc.BtcAddr var multisig_input []*wallet.MultisigAddr addrs_to_msign := make(map[string]bool) tx := new(btc.Tx) tx.Version = 1 tx.Lock_time = 0 outcnt, _ := strconv.ParseUint(r.Form["outcnt"][0], 10, 32) wallet.BalanceMutex.Lock() for i := 1; i <= int(outcnt); i++ { is := fmt.Sprint(i) if len(r.Form["txout"+is]) == 1 && r.Form["txout"+is][0] == "on" { hash := btc.NewUint256FromString(r.Form["txid"+is][0]) if hash != nil { vout, er := strconv.ParseUint(r.Form["txvout"+is][0], 10, 32) if er == nil { var po = btc.TxPrevOut{Hash: hash.Hash, Vout: uint32(vout)} for j := range wallet.MyBalance { if wallet.MyBalance[j].TxPrevOut == po { thisbal = append(thisbal, wallet.MyBalance[j]) // Add the input to our tx tin := new(btc.TxIn) tin.Input = wallet.MyBalance[j].TxPrevOut tin.Sequence = 0xffffffff tx.TxIn = append(tx.TxIn, tin) // Add new multisig address description _, msi := wallet.IsMultisig(wallet.MyBalance[j].BtcAddr) multisig_input = append(multisig_input, msi) if msi != nil { for ai := range msi.ListOfAddres { addrs_to_msign[msi.ListOfAddres[ai]] = true } } // Add the value to total input value totalinput += wallet.MyBalance[j].Value // If no change specified, use the first input addr as it if change_addr == nil { change_addr = wallet.MyBalance[j].BtcAddr } } } } } } } wallet.BalanceMutex.Unlock() for i := 1; ; i++ { adridx := fmt.Sprint("adr", i) btcidx := fmt.Sprint("btc", i) if len(r.Form[adridx]) != 1 || len(r.Form[btcidx]) != 1 { break } if len(r.Form[adridx][0]) > 1 { addr, er := btc.NewAddrFromString(r.Form[adridx][0]) if er == nil { am, er := btc.StringToSatoshis(r.Form[btcidx][0]) if er == nil && am > 0 { if pay_cmd == "" { pay_cmd = "wallet -useallinputs -send " } else { pay_cmd += "," } pay_cmd += addr.Enc58str + "=" + btc.UintToBtc(am) outs, er := btc.NewSpendOutputs(addr, am, common.CFG.Testnet) if er != nil { err = er.Error() goto error } tx.TxOut = append(tx.TxOut, outs...) spentsofar += am } else { err = "Incorrect amount (" + r.Form[btcidx][0] + ") for Output #" + fmt.Sprint(i) goto error } } else { err = "Incorrect address (" + r.Form[adridx][0] + ") for Output #" + fmt.Sprint(i) goto error } } } if pay_cmd == "" { err = "No inputs selected" goto error } am, er := btc.StringToSatoshis(r.Form["txfee"][0]) if er != nil { err = "Incorrect fee value: " + r.Form["txfee"][0] goto error } pay_cmd += " -fee " + r.Form["txfee"][0] spentsofar += am if len(r.Form["change"][0]) > 1 { addr, er := btc.NewAddrFromString(r.Form["change"][0]) if er != nil { err = "Incorrect change address: " + r.Form["change"][0] goto error } change_addr = addr } pay_cmd += " -change " + change_addr.String() if totalinput > spentsofar { // Add change output outs, er := btc.NewSpendOutputs(change_addr, totalinput-spentsofar, common.CFG.Testnet) if er != nil { err = er.Error() goto error } tx.TxOut = append(tx.TxOut, outs...) } buf := new(bytes.Buffer) zi := zip.NewWriter(buf) was_tx := make(map[[32]byte]bool, len(thisbal)) for i := range thisbal { if was_tx[thisbal[i].TxPrevOut.Hash] { continue } was_tx[thisbal[i].TxPrevOut.Hash] = true txid := btc.NewUint256(thisbal[i].TxPrevOut.Hash[:]) fz, _ := zi.Create("balance/" + txid.String() + ".tx") wallet.GetRawTransaction(thisbal[i].MinedAt, txid, fz) } fz, _ := zi.Create("balance/unspent.txt") for i := range thisbal { fmt.Fprintln(fz, thisbal[i].UnspentTextLine()) } if len(addrs_to_msign) > 0 { // Multisig (or mixed) transaction ... for i := range multisig_input { if multisig_input[i] == nil { continue } d, er := hex.DecodeString(multisig_input[i].RedeemScript) if er != nil { println("ERROR parsing hex RedeemScript:", er.Error()) continue } ms, er := btc.NewMultiSigFromP2SH(d) if er != nil { println("ERROR parsing bin RedeemScript:", er.Error()) continue } tx.TxIn[i].ScriptSig = ms.Bytes() } fz, _ = zi.Create("multi_" + common.CFG.PayCommandName) fmt.Fprintln(fz, "wallet -raw tx2sign.txt") for k, _ := range addrs_to_msign { fmt.Fprintln(fz, "wallet -msign", k, "-raw ...") } } else { if pay_cmd != "" { fz, _ = zi.Create(common.CFG.PayCommandName) fz.Write([]byte(pay_cmd)) } } // Non-multisig transaction ... fz, _ = zi.Create("tx2sign.txt") fz.Write([]byte(hex.EncodeToString(tx.Serialize()))) zi.Close() w.Header()["Content-Type"] = []string{"application/zip"} w.Write(buf.Bytes()) return } else { err = "Bad request" } error: s := load_template("send_error.html") write_html_head(w, r) s = strings.Replace(s, "<!--ERROR_MSG-->", err, 1) w.Write([]byte(s)) write_html_tail(w) }