Example #1
0
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)
}
Example #2
0
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)
}
Example #3
0
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)
}