Ejemplo n.º 1
0
// parse the "-send ..." parameter
func parse_spend() {
	// No dump, so send money...
	outs := strings.Split(*send, ",")
	sendTo = make([]oneSendTo, len(outs))

	for i := range outs {
		tmp := strings.Split(strings.Trim(outs[i], " "), "=")
		if len(tmp) != 2 {
			println("The otputs must be in a format address1=amount1[,addressN=amountN]\007")
			os.Exit(1)
		}

		a, e := btc.NewAddrFromString(tmp[0])
		if e != nil {
			println("NewAddrFromString:", e.Error(), "\007")
			os.Exit(1)
		}
		sendTo[i].addr = a

		am, e := strconv.ParseFloat(tmp[1], 64)
		if e != nil {
			println("ParseFloat:", e.Error(), "\007")
			os.Exit(1)
		}
		sendTo[i].amount = uint64(am * 1e8)
		spendBtc += sendTo[i].amount
	}
	feeBtc = uint64(*fee * 1e8)
}
Ejemplo n.º 2
0
// return the change addrress or nil if there will be no change
func get_change_addr() (chng *btc.BtcAddr) {
	if *change != "" {
		var e error
		chng, e = btc.NewAddrFromString(*change)
		if e != nil {
			println("Change address:", e.Error())
			os.Exit(1)
		}
		return
	}

	// If change address not specified, send it back to the first input
	uo := UO(unspentOuts[0])
	for j := range publ_addrs {
		if publ_addrs[j].Owns(uo.Pk_script) {
			if is_stealth[j] {
				println("Cannot send change to a stealth address. Use -change param")
				os.Exit(1)
			}
			chng = publ_addrs[j]
			return
		}
	}

	fmt.Println("You do not own the address of the first input, nor specified -change")
	os.Exit(1)
	return
}
Ejemplo n.º 3
0
// parse the "-send ..." parameter
func parse_spend() {
	outs := strings.Split(*send, ",")

	for i := range outs {
		tmp := strings.Split(strings.Trim(outs[i], " "), "=")
		if len(tmp) != 2 {
			println("The otputs must be in a format address1=amount1[,addressN=amountN]")
			os.Exit(1)
		}

		a, e := btc.NewAddrFromString(tmp[0])
		if e != nil {
			println("NewAddrFromString:", e.Error())
			os.Exit(1)
		}

		am, er := btc.StringToSatoshis(tmp[1])
		if er != nil {
			println("Incorrect amount: ", tmp[1], er.Error())
			os.Exit(1)
		}
		if *subfee {
			am -= curFee
		}

		sendTo = append(sendTo, oneSendTo{addr: a, amount: am})
		spendBtc += am
	}
}
Ejemplo n.º 4
0
func dump_prvkey() {
	if *dumppriv == "*" {
		// Dump all private keys
		for i := range priv_keys {
			if len(publ_addrs[i].Pubkey) == 33 {
				fmt.Println(sec2b58com(priv_keys[i]), publ_addrs[i].String(), labels[i])
			} else {
				fmt.Println(sec2b58unc(priv_keys[i]), publ_addrs[i].String(), labels[i])
			}
		}
	} else {
		// single key
		a, e := btc.NewAddrFromString(*dumppriv)
		if e != nil {
			println("Dump Private Key:", e.Error())
			return
		}
		if a.Version != verbyte {
			println("Dump Private Key: Version byte mismatch", a.Version, verbyte)
			return
		}
		for i := range priv_keys {
			if publ_addrs[i].Hash160 == a.Hash160 {
				if len(publ_addrs[i].Pubkey) == 33 {
					fmt.Println(sec2b58com(priv_keys[i]), publ_addrs[i].String(), labels[i])
				} else {
					fmt.Println(sec2b58unc(priv_keys[i]), publ_addrs[i].String(), labels[i])
				}
				return
			}
		}
		println("Dump Private Key:", a.String(), "not found it the wallet")
	}
}
Ejemplo n.º 5
0
func LoadWalfile(fn string, included int) (addrs []*btc.BtcAddr) {
	waldir, walname := filepath.Split(fn)
	if walname[0] == '.' {
		walname = walname[1:] // remove trailing dot (from hidden wallets)
	}
	f, e := os.Open(fn)
	if e != nil {
		println(e.Error())
		return
	}
	defer f.Close()
	rd := bufio.NewReader(f)
	linenr := 0
	for {
		var l string
		l, e = rd.ReadString('\n')
		space_first := len(l) > 0 && l[0] == ' '
		l = strings.Trim(l, " \t\r\n")
		linenr++
		//println(fmt.Sprint(fn, ":", linenr), "...")
		if len(l) > 0 {
			if l[0] == '@' {
				if included > 3 {
					println(fmt.Sprint(fn, ":", linenr), "Too many nested wallets")
				} else {
					ifn := strings.Trim(l[1:], " \n\t\t")
					addrs = append(addrs, LoadWalfile(waldir+ifn, included+1)...)
				}
			} else {
				var s string
				if l[0] != '#' {
					s = l
				} else if !PrecachingComplete && len(l) > 10 && l[1] == '1' {
					s = l[1:] // While pre-caching addresses, include ones that are commented out
				}
				if s != "" {
					ls := strings.SplitN(s, " ", 2)
					if len(ls) > 0 {
						a, e := btc.NewAddrFromString(ls[0])
						if e != nil {
							println(fmt.Sprint(fn, ":", linenr), e.Error())
						} else {
							a.Extra.Wallet = walname
							if len(ls) > 1 {
								a.Extra.Label = ls[1]
							}
							a.Extra.Virgin = space_first
							addrs = append(addrs, a)
						}
					}
				}
			}
		}
		if e != nil {
			break
		}
	}
	return
}
Ejemplo n.º 6
0
func main() {
	if len(os.Args) < 3 {
		fmt.Println("Specify at least two parameters:")
		fmt.Println(" 1) The base58 encoded bitcoin addres, that the signature was made with")
		fmt.Println(" 2) The base64 encoded signature for the message...")
		fmt.Println("If you specify a 3rd parameter - this will be assumed to be the message you want to verify")
		fmt.Println("If you do not specify a 3rd parameter - the message will be read from stdin")
		return
	}
	ad, er := btc.NewAddrFromString(os.Args[1])
	if er != nil {
		println("Address:", er.Error())
		return
	}

	nv, btcsig, er := btc.ParseMessageSignature(os.Args[2])
	if er != nil {
		println("ParseMessageSignature:", er.Error())
		return
	}

	var msg []byte
	if len(os.Args) < 4 {
		msg, _ = ioutil.ReadAll(os.Stdin)
	} else {
		msg = []byte(os.Args[3])
	}

	hash := make([]byte, 32)
	btc.HashFromMessage(msg, hash)

	compressed := false
	if nv >= 31 {
		//println("compressed key")
		nv -= 4
		compressed = true
	}

	pub := btcsig.RecoverPublicKey(hash[:], int(nv-27))
	if pub != nil {
		pk := pub.Bytes(compressed)
		ok := btc.EcdsaVerify(pk, btcsig.Bytes(), hash)
		if ok {
			sa := btc.NewAddrFromPubkey(pk, ad.Version)
			if ad.Hash160 != sa.Hash160 {
				fmt.Println("BAD signature for", ad.String())
				os.Exit(1)
			} else {
				fmt.Println("Good signature for", sa.String())
			}
		} else {
			println("BAD signature")
			os.Exit(1)
		}
	} else {
		println("BAD, BAD, BAD signature")
		os.Exit(1)
	}
}
Ejemplo n.º 7
0
func list_unspent(addr string) {
	fmt.Println("Checking unspent coins for addr", addr)
	var a [1]*btc.BtcAddr
	var e error
	a[0], e = btc.NewAddrFromString(addr)
	if e != nil {
		println(e.Error())
		return
	}
	unsp := BlockChain.GetAllUnspent(a[:], false)
	var sum uint64
	for i := range unsp {
		fmt.Println(unsp[i].String())
		sum += unsp[i].Value
	}
	fmt.Printf("Total %.8f unspent BTC at address %s\n", float64(sum)/1e8, a[0].String())
}
Ejemplo n.º 8
0
func LoadWalfile(fn string, included bool) (addrs []*btc.BtcAddr) {
	waldir, walname := filepath.Split(fn)
	f, e := os.Open(fn)
	if e != nil {
		println(e.Error())
		return
	}
	defer f.Close()
	rd := bufio.NewReader(f)
	linenr := 0
	for {
		var l string
		l, e = rd.ReadString('\n')
		l = strings.Trim(l, " \t\r\n")
		linenr++
		//println(fmt.Sprint(fn, ":", linenr), "...")
		if len(l) > 0 {
			if l[0] == '@' {
				if included {
					println(fmt.Sprint(fn, ":", linenr), "You cannot include wallets recursively")
				} else {
					ifn := strings.Trim(l[1:], " \n\t\t")
					addrs = append(addrs, LoadWalfile(waldir+ifn, true)...)
				}
			} else if l[0] != '#' {
				ls := strings.SplitN(l, " ", 2)
				if len(ls) > 0 {
					a, e := btc.NewAddrFromString(ls[0])
					if e != nil {
						println(fmt.Sprint(fn, ":", linenr), e.Error())
					} else {
						if len(ls) > 1 {
							a.Label = strings.Trim(ls[1], " \n\t\t")
						}
						a.Label += "@" + walname
						addrs = append(addrs, a)
					}
				}
			}
		}
		if e != nil {
			break
		}
	}
	return
}
Ejemplo n.º 9
0
func parse_batch() {
	f, e := os.Open(*batch)
	if e == nil {
		defer f.Close()
		td := bufio.NewReader(f)
		var lcnt int
		for {
			li, _, _ := td.ReadLine()
			if li == nil {
				break
			}
			lcnt++
			tmp := strings.SplitN(strings.Trim(string(li), " "), "=", 2)
			if len(tmp) < 2 {
				println("Error in the batch file line", lcnt)
				os.Exit(1)
			}
			if tmp[0][0] == '#' {
				continue // Just a comment-line
			}

			a, e := btc.NewAddrFromString(tmp[0])
			if e != nil {
				println("NewAddrFromString:", e.Error())
				os.Exit(1)
			}

			am, e := btc.StringToSatoshis(tmp[1])
			if e != nil {
				println("StringToSatoshis:", e.Error())
				os.Exit(1)
			}

			sendTo = append(sendTo, oneSendTo{addr: a, amount: am})
			spendBtc += am
		}
	} else {
		println(e.Error())
		os.Exit(1)
	}
}
Ejemplo n.º 10
0
// parse the "-send ..." parameter
func parse_spend() {
	outs := strings.Split(*send, ",")

	for i := range outs {
		tmp := strings.Split(strings.Trim(outs[i], " "), "=")
		if len(tmp) != 2 {
			println("The otputs must be in a format address1=amount1[,addressN=amountN]")
			os.Exit(1)
		}

		a, e := btc.NewAddrFromString(tmp[0])
		if e != nil {
			println("NewAddrFromString:", e.Error())
			os.Exit(1)
		}

		am := btc.ParseValue(tmp[1])
		sendTo = append(sendTo, oneSendTo{addr: a, amount: am})
		spendBtc += am
	}
}
Ejemplo n.º 11
0
// return the change addrress or nil if there will be no change
func get_change_addr() (chng *btc.BtcAddr) {
	if *change != "" {
		var e error
		chng, e = btc.NewAddrFromString(*change)
		if e != nil {
			println("Change address:", e.Error(), "\007")
			os.Exit(1)
		}
	}

	// If change address not specified, send it back to the first input
	uo := UO(unspentOuts[0])
	for j := range publ_addrs {
		if publ_addrs[j].Owns(uo.Pk_script) {
			chng = publ_addrs[j]
			return
		}
	}

	fmt.Println("You do not own the address of the first input\007")
	os.Exit(1)
	return
}
Ejemplo n.º 12
0
// Load public wallet from a text file
func NewWallet(fn string) (wal *OneWallet) {
	f, e := os.Open(fn)
	if e != nil {
		println(e.Error())
		return
	}
	defer f.Close()
	wal = new(OneWallet)
	wal.FileName = fn
	rd := bufio.NewReader(f)
	for {
		var l string
		l, e = rd.ReadString('\n')
		l = strings.Trim(l, " \t\r\n")
		if len(l) > 0 && l[0] != '#' {
			ls := strings.SplitN(l, " ", 2)
			if len(ls) > 0 {
				a, e := btc.NewAddrFromString(ls[0])
				if e != nil {
					println(l, ": ", e.Error())
				} else {
					if len(ls) > 1 {
						a.Label = strings.Trim(ls[1], " \n\t\t")
					}
					wal.Addrs = append(wal.Addrs, a)
				}
			}
		}
		if e != nil {
			break
		}
	}
	if len(wal.Addrs) == 0 {
		wal = nil
	}
	return
}
Ejemplo n.º 13
0
func NewWallet(fn string) (wal *oneWallet) {
	f, e := os.Open(fn)
	if e != nil {
		println(e.Error())
		return
	}
	defer f.Close()
	wal = new(oneWallet)
	rd := bufio.NewReader(f)
	for {
		var l string
		l, e = rd.ReadString('\n')
		l = strings.Trim(l, " \t\r\n")
		if len(l) > 0 && l[0] != '#' {
			ls := strings.SplitN(l, " ", 2)
			if len(ls) > 0 {
				a, e := btc.NewAddrFromString(ls[0])
				if e != nil {
					println(l, ": ", e.Error())
				} else {
					wal.addrs = append(wal.addrs, a)
					if len(ls) > 1 {
						wal.label = append(wal.label, strings.Trim(ls[1], " \n\t\t"))
					} else {
						wal.label = append(wal.label, "")
					}
				}
			}
		}
		if e != nil {
			break
		}
	}
	println(len(wal.addrs), "addresses loaded from", fn)
	return
}
Ejemplo n.º 14
0
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)
}
Ejemplo n.º 15
0
func sign_message() {
	ad2s, e := btc.NewAddrFromString(*signaddr)
	if e != nil {
		println(e.Error())
		return
	}

	var privkey *ecdsa.PrivateKey
	for i := range publ_addrs {
		if publ_addrs[i].Hash160 == ad2s.Hash160 {
			privkey = new(ecdsa.PrivateKey)
			pub, e := btc.NewPublicKey(publ_addrs[i].Pubkey)
			if e != nil {
				println(e.Error())
				return
			}
			privkey.PublicKey = pub.PublicKey
			privkey.D = new(big.Int).SetBytes(priv_keys[i][:])
			break
		}
	}
	if privkey == nil {
		println("You do not have a private key for", ad2s.String())
		return
	}

	var msg []byte
	if *message == "" {
		msg, _ = ioutil.ReadAll(os.Stdin)
	} else {
		msg = []byte(*message)
	}

	hash := make([]byte, 32)
	btc.HashFromMessage(msg, hash)

	btcsig := new(btc.Signature)
	var sb [65]byte
	sb[0] = 27
	if !*uncompressed {
		sb[0] += 4
	}

	btcsig.R, btcsig.S, e = ecdsa_Sign(privkey, hash)
	if e != nil {
		println(e.Error())
		return
	}

	rd := btcsig.R.Bytes()
	sd := btcsig.S.Bytes()
	copy(sb[1+32-len(rd):], rd)
	copy(sb[1+64-len(sd):], sd)

	rpk := btcsig.RecoverPublicKey(hash[:], 0)
	sa := btc.NewAddrFromPubkey(rpk.Bytes(!*uncompressed), ad2s.Version)
	if sa.Hash160 == ad2s.Hash160 {
		fmt.Println(base64.StdEncoding.EncodeToString(sb[:]))
		return
	}

	rpk = btcsig.RecoverPublicKey(hash[:], 1)
	sa = btc.NewAddrFromPubkey(rpk.Bytes(!*uncompressed), ad2s.Version)
	if sa.Hash160 == ad2s.Hash160 {
		sb[0]++
		fmt.Println(base64.StdEncoding.EncodeToString(sb[:]))
		return
	}
	println("Something went wrong. The message has not been signed.")
}
Ejemplo n.º 16
0
// this function signs either a message or a raw transaction hash
func sign_message() {
	var hash []byte

	if *signhash != "" {
		var er error
		hash, er = hex.DecodeString(*signhash)
		if er != nil {
			println("Incorrect content of -hash parameter")
			println(er.Error())
			return
		}
	}

	ad2s, e := btc.NewAddrFromString(*signaddr)
	if e != nil {
		println(e.Error())
		if *signhash != "" {
			println("Always use -sign <addr> along with -hash <msghash>")
		}
		return
	}

	var privkey []byte
	var compr bool

	for i := range publ_addrs {
		if publ_addrs[i].Hash160 == ad2s.Hash160 {
			privkey = priv_keys[i][:]
			compr = compressed_key[i]

			// Sign raw hash?
			if hash != nil {
				txsig := new(btc.Signature)
				txsig.HashType = 0x01
				r, s, e := btc.EcdsaSign(privkey, hash)
				if e != nil {
					println(e.Error())
					return
				}
				txsig.R.Set(r)
				txsig.S.Set(s)
				fmt.Println("PublicKey:", hex.EncodeToString(publ_addrs[i].Pubkey))
				fmt.Println(hex.EncodeToString(txsig.Bytes()))
				return
			}

			break
		}
	}
	if privkey == nil {
		println("You do not have a private key for", ad2s.String())
		return
	}

	var msg []byte
	if *message == "" {
		msg, _ = ioutil.ReadAll(os.Stdin)
	} else {
		msg = []byte(*message)
	}

	hash = make([]byte, 32)
	btc.HashFromMessage(msg, hash)

	btcsig := new(btc.Signature)
	var sb [65]byte
	sb[0] = 27
	if compr {
		sb[0] += 4
	}

	r, s, e := btc.EcdsaSign(privkey, hash)
	if e != nil {
		println(e.Error())
		return
	}
	btcsig.R.Set(r)
	btcsig.S.Set(s)

	rd := btcsig.R.Bytes()
	sd := btcsig.S.Bytes()
	copy(sb[1+32-len(rd):], rd)
	copy(sb[1+64-len(sd):], sd)

	rpk := btcsig.RecoverPublicKey(hash[:], 0)
	sa := btc.NewAddrFromPubkey(rpk.Bytes(compr), ad2s.Version)
	if sa.Hash160 == ad2s.Hash160 {
		fmt.Println(base64.StdEncoding.EncodeToString(sb[:]))
		return
	}

	rpk = btcsig.RecoverPublicKey(hash[:], 1)
	sa = btc.NewAddrFromPubkey(rpk.Bytes(compr), ad2s.Version)
	if sa.Hash160 == ad2s.Hash160 {
		sb[0]++
		fmt.Println(base64.StdEncoding.EncodeToString(sb[:]))
		return
	}
	println("Something went wrong. The message has not been signed.")
}
Ejemplo n.º 17
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 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)
}
Ejemplo n.º 18
0
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)
}
Ejemplo n.º 19
0
func multisig_sign() {
	tx := raw_tx_from_file(*rawtx)
	if tx == nil {
		println("ERROR: Cannot decode the raw multisig transaction")
		println("Always use -msign <addr> along with -raw multi2sign.txt")
		return
	}

	ad2s, e := btc.NewAddrFromString(*multisign)
	if e != nil {
		println("BTC addr:", e.Error())
		return
	}

	var privkey *ecdsa.PrivateKey
	//var compr bool

	for i := range publ_addrs {
		if publ_addrs[i].Hash160 == ad2s.Hash160 {
			privkey = new(ecdsa.PrivateKey)
			pub, e := btc.NewPublicKey(publ_addrs[i].Pubkey)
			if e != nil {
				println("PubKey:", e.Error())
				return
			}
			privkey.PublicKey = pub.PublicKey
			privkey.D = new(big.Int).SetBytes(priv_keys[i][:])
			//compr = compressed_key[i]
			break
		}
	}

	if privkey == nil {
		println("You do not know a key for address", ad2s.String())
		return
	}

	for i := range tx.TxIn {
		ms, er := btc.NewMultiSigFromScript(tx.TxIn[i].ScriptSig)
		if er != nil {
			println("WARNING: Input", i, "- not multisig:", er.Error())
			continue
		}
		hash := tx.SignatureHash(ms.P2SH(), i, btc.SIGHASH_ALL)
		//fmt.Println("Input number", i, len(ms.Signatures), " - hash to sign:", hex.EncodeToString(hash))

		btcsig := &btc.Signature{HashType: 0x01}
		btcsig.R, btcsig.S, e = btc.EcdsaSign(privkey, hash)
		if e != nil {
			println(e.Error())
			return
		}

		ms.Signatures = append(ms.Signatures, btcsig)
		tx.TxIn[i].ScriptSig = ms.Bytes()
	}

	// Now re-order the signatures as they shall be:
	for i := range tx.TxIn {
		ms, er := btc.NewMultiSigFromScript(tx.TxIn[i].ScriptSig)
		if er != nil {
			//println(er.Error())
			continue
		}
		hash := tx.SignatureHash(ms.P2SH(), i, btc.SIGHASH_ALL)
		//fmt.Println("Input number", i, " - hash to sign:", hex.EncodeToString(hash))
		//fmt.Println(" ... number of signatures:", len(ms.Signatures))

		var sigs []*btc.Signature
		for ki := range ms.PublicKeys {
			//pk := btc.NewPublicKey(ms.PublicKeys[ki])
			//fmt.Println(ki, hex.EncodeToString(ms.PublicKeys[ki]))
			var sig *btc.Signature
			for si := range ms.Signatures {
				if btc.EcdsaVerify(ms.PublicKeys[ki], ms.Signatures[si].Bytes(), hash) {
					//fmt.Println("Key number", ki, "has signature number", si)
					sig = ms.Signatures[si]
					break
				}
			}
			if sig != nil {
				sigs = append(sigs, sig)
			} else if *verbose {
				fmt.Println("WARNING: Key number", ki, "has no matching signature")
			}

			if !*allowextramsigns && uint(len(sigs)) >= ms.SigsNeeded {
				break
			}

		}

		if len(ms.Signatures) > len(sigs) {
			fmt.Println("WARNING: Some signatures are obsolete and will be removed", len(ms.Signatures), "=>", len(sigs))
		} else if len(ms.Signatures) < len(sigs) {
			fmt.Println("It appears that same key is re-used.", len(sigs)-len(ms.Signatures), "more signatures were added")
		}
		ms.Signatures = sigs
		tx.TxIn[i].ScriptSig = ms.Bytes()
	}

	write_tx_file(tx)
}
Ejemplo n.º 20
0
func main() {
	fmt.Println("Gocoin FetchBalnace version", btc.SourcesTag)

	if len(os.Args) < 2 {
		print_help()
		return
	}

	var addrs []*btc.BtcAddr

	if len(os.Args) == 2 {
		fi, er := os.Stat(os.Args[1])
		if er == nil && fi.Size() > 10 && !fi.IsDir() {
			wal := wallet.NewWallet(os.Args[1])
			if wal != nil {
				fmt.Println("Found", len(wal.Addrs), "address(es) in", wal.FileName)
				addrs = wal.Addrs
			}
		}
	}

	if len(addrs) == 0 {
		for i := 1; i < len(os.Args); i++ {
			a, e := btc.NewAddrFromString(os.Args[i])
			if e != nil {
				println(os.Args[i], ": ", e.Error())
				return
			} else {
				addrs = append(addrs, a)
			}
		}
	}

	if len(addrs) == 0 {
		print_help()
		return
	}

	url := "http://blockchain.info/unspent?active="
	for i := range addrs {
		if i > 0 {
			url += "|"
		}
		url += addrs[i].String()
	}

	var sum, outcnt uint64
	r, er := http.Get(url)
	if er == nil && r.StatusCode == 200 {
		defer r.Body.Close()
		c, _ := ioutil.ReadAll(r.Body)
		var r restype
		er = json.Unmarshal(c[:], &r)
		if er == nil {
			os.RemoveAll("balance/")
			os.Mkdir("balance/", 0700)
			unsp, _ := os.Create("balance/unspent.txt")
			for i := 0; i < len(r.Unspent_outputs); i++ {
				pkscr, _ := hex.DecodeString(r.Unspent_outputs[i].Script)
				b58adr := "???"
				if pkscr != nil {
					ba := btc.NewAddrFromPkScript(pkscr, btc.ADDRVER_BTC)
					if ba != nil {
						b58adr = ba.String()
					}
				}
				txidlsb, _ := hex.DecodeString(r.Unspent_outputs[i].Tx_hash)
				if txidlsb != nil {
					txid := btc.NewUint256(txidlsb)
					if GetTx(txid, int(r.Unspent_outputs[i].Tx_output_n)) {
						fmt.Fprintf(unsp, "%s-%03d # %.8f @ %s, %d confs\n",
							txid.String(), r.Unspent_outputs[i].Tx_output_n,
							float64(r.Unspent_outputs[i].Value)/1e8,
							b58adr, r.Unspent_outputs[i].Confirmations)
						sum += r.Unspent_outputs[i].Value
						outcnt++
					} else {
						fmt.Printf(" - cannot fetch %s-%03d\n", txid.String(), r.Unspent_outputs[i].Tx_output_n)
					}
				}
			}
			unsp.Close()
			if outcnt > 0 {
				fmt.Printf("Total %.8f BTC in %d unspent outputs.\n", float64(sum)/1e8, outcnt)
				fmt.Println("The data has been stored in 'balance' folder.")
				fmt.Println("Use it with the wallet app to spend any of it.")
			} else {
				fmt.Println("The fateched balance is empty.")
			}
		} else {
			fmt.Println("Unspent json.Unmarshal", er.Error())
		}
	} else {
		if er != nil {
			fmt.Println("Unspent ", er.Error())
		} else {
			fmt.Println("Unspent HTTP StatusCode", r.StatusCode)
		}
	}
}
Ejemplo n.º 21
0
func main() {
	var msg []byte

	flag.Parse()

	if *help || *addr == "" || *sign == "" {
		flag.PrintDefaults()
		return
	}

	ad, er := btc.NewAddrFromString(*addr)
	if er != nil {
		println("Address:", er.Error())
		flag.PrintDefaults()
		return
	}

	nv, btcsig, er := btc.ParseMessageSignature(*sign)
	if er != nil {
		println("ParseMessageSignature:", er.Error())
		return
	}

	if *mess != "" {
		msg = []byte(*mess)
	} else if *mfil != "" {
		msg, er = ioutil.ReadFile(*mfil)
		if er != nil {
			println(er.Error())
			return
		}
	} else {
		fmt.Println("Enter the message:")
		msg, _ = ioutil.ReadAll(os.Stdin)
	}

	if *unix {
		fmt.Println("Enforcing Unix text format")
		msg = []byte(strings.Replace(string(msg), "\r", "", -1))
	}

	hash := make([]byte, 32)
	btc.HashFromMessage(msg, hash)

	compressed := false
	if nv >= 31 {
		//println("compressed key")
		nv -= 4
		compressed = true
	}

	pub := btcsig.RecoverPublicKey(hash[:], int(nv-27))
	if pub != nil {
		pk := pub.Bytes(compressed)
		ok := btc.EcdsaVerify(pk, btcsig.Bytes(), hash)
		if ok {
			sa := btc.NewAddrFromPubkey(pk, ad.Version)
			if ad.Hash160 != sa.Hash160 {
				fmt.Println("BAD signature for", ad.String())
				os.Exit(1)
			} else {
				fmt.Println("Good signature for", sa.String())
			}
		} else {
			println("BAD signature")
			os.Exit(1)
		}
	} else {
		println("BAD, BAD, BAD signature")
		os.Exit(1)
	}
}