func xml_balance(w http.ResponseWriter, r *http.Request) { if !ipchecker(r) { return } w.Header()["Content-Type"] = []string{"text/xml"} w.Write([]byte("<unspent>")) wallet.LockBal() for i := range wallet.MyBalance { w.Write([]byte("<output>")) fmt.Fprint(w, "<txid>", btc.NewUint256(wallet.MyBalance[i].TxPrevOut.Hash[:]).String(), "</txid>") fmt.Fprint(w, "<vout>", wallet.MyBalance[i].TxPrevOut.Vout, "</vout>") fmt.Fprint(w, "<value>", wallet.MyBalance[i].Value, "</value>") fmt.Fprint(w, "<inblock>", wallet.MyBalance[i].MinedAt, "</inblock>") fmt.Fprint(w, "<blocktime>", get_block_time(wallet.MyBalance[i].MinedAt), "</blocktime>") fmt.Fprint(w, "<addr>", wallet.MyBalance[i].BtcAddr.String(), "</addr>") fmt.Fprint(w, "<wallet>", html.EscapeString(wallet.MyBalance[i].BtcAddr.Extra.Wallet), "</wallet>") fmt.Fprint(w, "<label>", html.EscapeString(wallet.MyBalance[i].BtcAddr.Extra.Label), "</label>") fmt.Fprint(w, "<virgin>", fmt.Sprint(wallet.MyBalance[i].BtcAddr.Extra.Virgin), "</virgin>") w.Write([]byte("</output>")) } wallet.UnlockBal() w.Write([]byte("</unspent>")) }
func show_balance_stats(p string) { println("CachedAddrs count:", len(wallet.CachedAddrs)) println("CacheUnspentIdx count:", len(wallet.CacheUnspentIdx)) println("CacheUnspent count:", len(wallet.CacheUnspent)) if p != "" { wallet.LockBal() for i := range wallet.CacheUnspent { fmt.Printf("%5d) %35s - %d unspent output(s)\n", i, wallet.CacheUnspent[i].BtcAddr.String(), len(wallet.CacheUnspent[i].AllUnspentTx)) /*for j := range wallet.CacheUnspent[i].AllUnspentTx { fmt.Printf(" %5d) %s\n", j, wallet.CacheUnspent[i].AllUnspentTx[j].String()) }*/ } wallet.UnlockBal() } }
func p_snd(w http.ResponseWriter, r *http.Request) { if !ipchecker(r) { return } s := load_template("send.html") wallet.LockBal() 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, "{ADDR_LABEL}", html.EscapeString(wallet.MyBalance[i].BtcAddr.Label), 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, "{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].BtcAddr.String(), 1) wal = templ_add(wal, "<!--UTXOROW-->", row) } for i := range wallet.MyWallet.Addrs { op := "<option value=\"" + wallet.MyWallet.Addrs[i].Enc58str + "\">" + wallet.MyWallet.Addrs[i].Enc58str + " (" + html.EscapeString(wallet.MyWallet.Addrs[i].Label) + ")</option>" //wal = strings.Replace(wal, "<!--ONECHANGEADDR-->", op, 1) wal = templ_add(wal, "<!--ONECHANGEADDR-->", op) } 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.UnlockBal() write_html_head(w, r) w.Write([]byte(s)) write_html_tail(w) }
func p_home(w http.ResponseWriter, r *http.Request) { if !ipchecker(r) { return } s := load_template("home.html") wallet.LockBal() if len(wallet.MyBalance) > 0 { wal := load_template("home_wal.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) 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 balance is <b>zero</b>", 1) } } wallet.UnlockBal() common.Last.Mutex.Lock() s = strings.Replace(s, "{LAST_BLOCK_HASH}", common.Last.Block.BlockHash.String(), 1) s = strings.Replace(s, "{LAST_BLOCK_HEIGHT}", fmt.Sprint(common.Last.Block.Height), 1) s = strings.Replace(s, "{LAST_BLOCK_TIME}", time.Unix(int64(common.Last.Block.Timestamp), 0).Format("2006/01/02 15:04:05"), 1) s = strings.Replace(s, "{LAST_BLOCK_DIFF}", common.NumberToString(btc.GetDifficulty(common.Last.Block.Bits)), 1) s = strings.Replace(s, "{LAST_BLOCK_RCVD}", time.Now().Sub(common.Last.Time).String(), 1) common.Last.Mutex.Unlock() s = strings.Replace(s, "{BLOCKS_CACHED}", fmt.Sprint(len(network.CachedBlocks)), 1) s = strings.Replace(s, "{KNOWN_PEERS}", fmt.Sprint(network.PeerDB.Count()), 1) s = strings.Replace(s, "{NODE_UPTIME}", time.Now().Sub(common.StartTime).String(), 1) s = strings.Replace(s, "{NET_BLOCK_QSIZE}", fmt.Sprint(len(network.NetBlocks)), 1) s = strings.Replace(s, "{NET_TX_QSIZE}", fmt.Sprint(len(network.NetTxs)), 1) network.Mutex_net.Lock() s = strings.Replace(s, "{OPEN_CONNS_TOTAL}", fmt.Sprint(len(network.OpenCons)), 1) s = strings.Replace(s, "{OPEN_CONNS_OUT}", fmt.Sprint(network.OutConsActive), 1) s = strings.Replace(s, "{OPEN_CONNS_IN}", fmt.Sprint(network.InConsActive), 1) network.Mutex_net.Unlock() common.LockBw() common.TickRecv() common.TickSent() s = strings.Replace(s, "{DL_SPEED_NOW}", fmt.Sprint(common.DlBytesPrevSec>>10), 1) s = strings.Replace(s, "{DL_SPEED_MAX}", fmt.Sprint(common.DownloadLimit>>10), 1) s = strings.Replace(s, "{DL_TOTAL}", common.BytesToString(common.DlBytesTotal), 1) s = strings.Replace(s, "{UL_SPEED_NOW}", fmt.Sprint(common.UlBytesPrevSec>>10), 1) s = strings.Replace(s, "{UL_SPEED_MAX}", fmt.Sprint(common.UploadLimit>>10), 1) s = strings.Replace(s, "{UL_TOTAL}", common.BytesToString(common.UlBytesTotal), 1) common.UnlockBw() network.ExternalIpMutex.Lock() for ip, cnt := range network.ExternalIp4 { s = strings.Replace(s, "{ONE_EXTERNAL_IP}", fmt.Sprintf("%dx%d.%d.%d.%d {ONE_EXTERNAL_IP}", cnt, byte(ip>>24), byte(ip>>16), byte(ip>>8), byte(ip)), 1) } network.ExternalIpMutex.Unlock() s = strings.Replace(s, "{ONE_EXTERNAL_IP}", "", 1) var ms runtime.MemStats runtime.ReadMemStats(&ms) s = strings.Replace(s, "{HEAP_SIZE_MB}", fmt.Sprint(ms.Alloc>>20), 1) s = strings.Replace(s, "{SYSMEM_USED_MB}", fmt.Sprint(ms.Sys>>20), 1) s = strings.Replace(s, "{ECDSA_VERIFY_COUNT}", fmt.Sprint(btc.EcdsaVerifyCnt), 1) common.LockCfg() dat, _ := json.Marshal(&common.CFG) common.UnlockCfg() s = strings.Replace(s, "{CONFIG_FILE}", strings.Replace(string(dat), ",\"", ", \"", -1), 1) write_html_head(w, r) w.Write([]byte(s)) write_html_tail(w) }
func dl_payment(w http.ResponseWriter, r *http.Request) { if !ipchecker(r) { return } var err string r.ParseForm() if len(r.Form["outcnt"]) == 1 { var thisbal btc.AllUnspentTx var pay_cmd string outcnt, _ := strconv.ParseUint(r.Form["outcnt"][0], 10, 32) wallet.LockBal() 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]) } } } } } } wallet.UnlockBal() for i := 1; ; i++ { is := fmt.Sprint(i) if len(r.Form["adr"+is]) != 1 { break } if len(r.Form["btc"+is]) != 1 { break } if len(r.Form["adr"+is][0]) > 1 { addr, er := btc.NewAddrFromString(r.Form["adr"+is][0]) if er == nil { am, er := strconv.ParseFloat(r.Form["btc"+is][0], 64) if er == nil && am > 0 { if pay_cmd == "" { pay_cmd = "wallet -useallinputs -send " } else { pay_cmd += "," } pay_cmd += addr.Enc58str + "=" + fmt.Sprintf("%.8f", am) } else { err = "Incorrect amount (" + r.Form["btc"+is][0] + ") for Output #" + is goto error } } else { err = "Incorrect address (" + r.Form["adr"+is][0] + ") for Output #" + is goto error } } } if pay_cmd != "" && len(r.Form["txfee"]) == 1 { pay_cmd += " -fee " + r.Form["txfee"][0] } if pay_cmd != "" && len(r.Form["change"]) == 1 && len(r.Form["change"][0]) > 1 { pay_cmd += " -change " + r.Form["change"][0] } 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.Fprintf(fz, "%s # %.8f BTC @ %s, %d confs\n", thisbal[i].TxPrevOut.String(), float64(thisbal[i].Value)/1e8, thisbal[i].BtcAddr.StringLab(), 1+common.Last.Block.Height-thisbal[i].MinedAt) } if pay_cmd != "" { fz, _ = zi.Create("pay_cmd.txt") fz.Write([]byte(pay_cmd)) } 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) }
func p_snd(w http.ResponseWriter, r *http.Request) { if !ipchecker(r) { return } s := load_template("send.html") wallet.LockBal() 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 += " ***" } 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, "{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].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) } // Address Book book := wallet.LoadWalfile(common.GocoinHomeDir+"wallet/ADDRESS", 0) for i := range book { row := "addrbook.push({'addr':'" + book[i].Enc58str + "', " + "'label':'" + book[i].Extra.Label + "', " + "'wallet':'" + book[i].Extra.Wallet + "'})\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.UnlockBal() write_html_head(w, r) w.Write([]byte(s)) write_html_tail(w) }
func dl_payment(w http.ResponseWriter, r *http.Request) { if !ipchecker(r) { return } var err string r.ParseForm() if len(r.Form["outcnt"]) == 1 { var thisbal btc.AllUnspentTx var pay_cmd string var totalinput, spentsofar uint64 var change_addr *btc.BtcAddr tx := new(btc.Tx) tx.Version = 1 tx.Lock_time = 0 outcnt, _ := strconv.ParseUint(r.Form["outcnt"][0], 10, 32) wallet.LockBal() 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) totalinput += wallet.MyBalance[j].Value if change_addr == nil { change_addr = wallet.MyBalance[j].BtcAddr } } } } } } } wallet.UnlockBal() 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) tout := new(btc.TxOut) tout.Value = am tout.Pk_script = addr.OutScript() tx.TxOut = append(tx.TxOut, tout) 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 tout := new(btc.TxOut) tout.Value = totalinput - spentsofar tout.Pk_script = change_addr.OutScript() tx.TxOut = append(tx.TxOut, tout) } 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.Fprintf(fz, "%s # %.8f BTC @ %s, %d confs\n", thisbal[i].TxPrevOut.String(), float64(thisbal[i].Value)/1e8, thisbal[i].BtcAddr.StringLab(), 1+common.Last.Block.Height-thisbal[i].MinedAt) } // pay_cmd.bat if pay_cmd != "" { fz, _ = zi.Create(common.CFG.PayCommandName) fz.Write([]byte(pay_cmd)) } // Raw 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) }
func dl_payment(w http.ResponseWriter, r *http.Request) { if !ipchecker(r) { return } var err string if len(r.Form["outcnt"]) == 1 { var thisbal btc.AllUnspentTx var pay_cmd string var totalinput, spentsofar uint64 var change_addr *btc.BtcAddr var multisig_input []*wallet.MultisigAddr var invalid_tx bool 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.LockBal() 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.UnlockBal() 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) tout := new(btc.TxOut) tout.Value = am tout.Pk_script = addr.OutScript() if tout.Pk_script != nil { tx.TxOut = append(tx.TxOut, tout) } else { invalid_tx = true } 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 tout := new(btc.TxOut) tout.Value = totalinput - spentsofar tout.Pk_script = change_addr.OutScript() tx.TxOut = append(tx.TxOut, tout) } 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.Fprintf(fz, "%s # %.8f BTC @ %s, %d confs\n", thisbal[i].TxPrevOut.String(), float64(thisbal[i].Value)/1e8, thisbal[i].BtcAddr.StringLab(), 1+common.Last.Block.Height-thisbal[i].MinedAt) } 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("multi2sign.txt") fz.Write([]byte(hex.EncodeToString(tx.Serialize()))) fz, _ = zi.Create("multi_" + common.CFG.PayCommandName) for k, _ := range addrs_to_msign { fmt.Fprintln(fz, "wallet -msign", k, "-raw ...") } } else { // Non-multisig transaction ... if !invalid_tx { fz, _ = zi.Create("tx2sign.txt") fz.Write([]byte(hex.EncodeToString(tx.Serialize()))) } if pay_cmd != "" { fz, _ = zi.Create(common.CFG.PayCommandName) fz.Write([]byte(pay_cmd)) } } 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) }