// 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) }
// 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 }
// 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 } }
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") } }
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 }
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) } }
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()) }
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 }
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) } }
// 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 } }
// 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 }
// 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 }
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 }
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 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.") }
// 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.") }
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) }
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 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) }
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) } } }
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) } }