func xmp_txs2s(w http.ResponseWriter, r *http.Request) { if !ipchecker(r) { return } r.ParseForm() if checksid(r) && len(r.Form["del"]) > 0 { tid := btc.NewUint256FromString(r.Form["del"][0]) if tid != nil { network.TxMutex.Lock() delete(network.TransactionsToSend, tid.Hash) network.TxMutex.Unlock() } } if checksid(r) && len(r.Form["send"]) > 0 { tid := btc.NewUint256FromString(r.Form["send"][0]) if tid != nil { network.TxMutex.Lock() if ptx, ok := network.TransactionsToSend[tid.Hash]; ok { network.TxMutex.Unlock() cnt := network.NetRouteInv(1, tid, nil) ptx.Invsentcnt += cnt } } } w.Header()["Content-Type"] = []string{"text/xml"} if len(r.Form["id"]) > 0 { output_tx_xml(w, r.Form["id"][0]) return } w.Write([]byte("<txpool>")) network.TxMutex.Lock() for k, v := range network.TransactionsToSend { w.Write([]byte("<tx>")) fmt.Fprint(w, "<id>", btc.NewUint256(k[:]).String(), "</id>") fmt.Fprint(w, "<time>", v.Firstseen.Unix(), "</time>") fmt.Fprint(w, "<len>", len(v.Data), "</len>") fmt.Fprint(w, "<own>", v.Own, "</own>") fmt.Fprint(w, "<firstseen>", v.Firstseen.Unix(), "</firstseen>") fmt.Fprint(w, "<invsentcnt>", v.Invsentcnt, "</invsentcnt>") fmt.Fprint(w, "<sentcnt>", v.SentCnt, "</sentcnt>") fmt.Fprint(w, "<sentlast>", v.Lastsent.Unix(), "</sentlast>") fmt.Fprint(w, "<volume>", v.Volume, "</volume>") fmt.Fprint(w, "<fee>", v.Fee, "</fee>") fmt.Fprint(w, "<blocked>", v.Blocked, "</blocked>") w.Write([]byte("</tx>")) } network.TxMutex.Unlock() w.Write([]byte("</txpool>")) }
func raw_tx(w http.ResponseWriter, r *http.Request) { if !ipchecker(r) { return } defer func() { if r := recover(); r != nil { fmt.Fprintln(w, "Error") if err, ok := r.(error); ok { fmt.Fprintln(w, err.Error()) } } }() r.ParseForm() if len(r.Form["id"]) == 0 { fmt.Println("No id given") return } txid := btc.NewUint256FromString(r.Form["id"][0]) fmt.Fprintln(w, "TxID:", txid.String()) if tx, ok := network.TransactionsToSend[txid.Hash]; ok { s, _, _, _, _ := usif.DecodeTx(tx.Tx) w.Write([]byte(s)) } else { fmt.Fprintln(w, "Not found") } }
func host_init() { BtcRootDir := BitcoinHome() if *datadir == "" { GocoinHomeDir = BtcRootDir + "gocoin/" } else { GocoinHomeDir = *datadir + "/" } if *testnet { // testnet3 DefaultTcpPort = 18333 GenesisBlock = btc.NewUint256FromString("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943") Magic = [4]byte{0x0B, 0x11, 0x09, 0x07} GocoinHomeDir += "tstnet/" AddrVersion = 0x6f BtcRootDir += "testnet3/" } else { DefaultTcpPort = 8333 GenesisBlock = btc.NewUint256FromString("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f") Magic = [4]byte{0xF9, 0xBE, 0xB4, 0xD9} GocoinHomeDir += "btcnet/" AddrVersion = 0x00 } fi, e := os.Stat(GocoinHomeDir + "blockchain.idx") if e != nil || fi.Size() < 100 { os.RemoveAll(GocoinHomeDir) fmt.Println("You seem to be running Gocoin for the fist time on this PC") fi, e = os.Stat(BtcRootDir + "blocks/blk00000.dat") if e == nil && fi.Size() > 1024*1024 { fmt.Println("There is a database from Satoshi client on your disk...") if ask_yes_no("Go you want to import this database into Gocoin?") { import_blockchain(BtcRootDir + "blocks") } } } fmt.Println("Opening blockchain...") sta := time.Now().UnixNano() BlockChain = btc.NewChain(GocoinHomeDir, GenesisBlock, *rescan) sto := time.Now().UnixNano() fmt.Printf("Blockchain open in %.3f seconds\n", float64(sto-sta)/1e9) if *nosync { BlockChain.DoNotSync = true fmt.Println("Syncing is disabled. Switch it on with 'sync' command") } }
func output_tx_xml(w http.ResponseWriter, id string) { txid := btc.NewUint256FromString(id) w.Write([]byte("<tx>")) fmt.Fprint(w, "<id>", id, "</id>") if t2s, ok := network.TransactionsToSend[txid.BIdx()]; ok { w.Write([]byte("<status>OK</status>")) tx := t2s.Tx w.Write([]byte("<inputs>")) for i := range tx.TxIn { w.Write([]byte("<input>")) var po *btc.TxOut inpid := btc.NewUint256(tx.TxIn[i].Input.Hash[:]) if txinmem, ok := network.TransactionsToSend[inpid.BIdx()]; ok { if int(tx.TxIn[i].Input.Vout) < len(txinmem.TxOut) { po = txinmem.TxOut[tx.TxIn[i].Input.Vout] } } else { po, _ = common.BlockChain.Unspent.UnspentGet(&tx.TxIn[i].Input) } if po != nil { ok := btc.VerifyTxScript(tx.TxIn[i].ScriptSig, po.Pk_script, i, tx, true) if !ok { w.Write([]byte("<status>Script FAILED</status>")) } else { w.Write([]byte("<status>OK</status>")) } fmt.Fprint(w, "<value>", po.Value, "</value>") fmt.Fprint(w, "<addr>", btc.NewAddrFromPkScript(po.Pk_script, common.Testnet).String(), "</addr>") fmt.Fprint(w, "<block>", po.BlockHeight, "</block>") } else { w.Write([]byte("<status>UNKNOWN INPUT</status>")) } w.Write([]byte("</input>")) } w.Write([]byte("</inputs>")) w.Write([]byte("<outputs>")) for i := range tx.TxOut { w.Write([]byte("<output>")) fmt.Fprint(w, "<value>", tx.TxOut[i].Value, "</value>") adr := btc.NewAddrFromPkScript(tx.TxOut[i].Pk_script, common.Testnet) if adr != nil { fmt.Fprint(w, "<addr>", adr.String(), "</addr>") } else { fmt.Fprint(w, "<addr>", "scr:"+hex.EncodeToString(tx.TxOut[i].Pk_script), "</addr>") } w.Write([]byte("</output>")) } w.Write([]byte("</outputs>")) } else { w.Write([]byte("<status>Not found</status>")) } w.Write([]byte("</tx>")) }
func dec_tx(par string) { txid := btc.NewUint256FromString(par) if txid == nil { fmt.Println("You must specify a valid transaction ID for this command.") list_txs("") return } if tx, ok := network.TransactionsToSend[txid.Hash]; ok { s, _, _, _, _ := usif.DecodeTx(tx.Tx) fmt.Println(s) } else { fmt.Println("No such transaction ID in the memory pool.") } }
func send_tx(par string) { txid := btc.NewUint256FromString(par) if txid == nil { fmt.Println("You must specify a valid transaction ID for this command.") list_txs("") return } if _, ok := TransactionsToSend[txid.Hash]; !ok { fmt.Println("No such transaction ID in the memory pool.") list_txs("") return } cnt := NetSendInv(1, txid.Hash[:], nil) fmt.Println("Transaction", txid.String(), "broadcasted to", cnt, "node(s)") fmt.Println("If it does not appear in the chain, you may want to redo it.") }
func main() { fmt.Println("Gocoin FetchTx version", btc.SourcesTag) if len(os.Args) < 2 { fmt.Println("Specify transaction id on the command line (MSB).") return } txid := btc.NewUint256FromString(os.Args[1]) rawtx := utils.GetTxFromWeb(txid) if rawtx == nil { fmt.Println("Error fetching the transaction") } else { ioutil.WriteFile(txid.String()+".tx", rawtx, 0666) } }
func GetTx(txid *btc.Uint256, vout int) bool { r, er := http.Get("http://blockexplorer.com/rawtx/" + txid.String()) if er == nil && r.StatusCode == 200 { defer r.Body.Close() c, _ := ioutil.ReadAll(r.Body) var txx onetx er = json.Unmarshal(c[:], &txx) if er == nil { tx := new(btc.Tx) tx.Version = txx.Ver tx.TxIn = make([]*btc.TxIn, len(txx.In)) for i := range txx.In { tx.TxIn[i] = new(btc.TxIn) tx.TxIn[i].Input.Hash = btc.NewUint256FromString(txx.In[i].Prev_out.Hash).Hash tx.TxIn[i].Input.Vout = txx.In[i].Prev_out.N tx.TxIn[i].ScriptSig, _ = btc.DecodeScript(txx.In[i].ScriptSig) tx.TxIn[i].Sequence = 0xffffffff } tx.TxOut = make([]*btc.TxOut, len(txx.Out)) for i := range txx.Out { tx.TxOut[i] = new(btc.TxOut) tx.TxOut[i].Value = btc.ParseValue(txx.Out[i].Value) tx.TxOut[i].Pk_script, _ = btc.DecodeScript(txx.Out[i].ScriptPubKey) } tx.Lock_time = txx.Lock_time rawtx := tx.Serialize() curid := btc.NewSha2Hash(rawtx) if !curid.Equal(txid) { fmt.Println("The downloaded transaction does not match its ID.") return false } ioutil.WriteFile("balance/"+curid.String()+".tx", rawtx, 0666) return true } else { fmt.Println("json.Unmarshal:", er.Error()) } } else { if er != nil { fmt.Println("http.Get:", er.Error()) } else { fmt.Println("StatusCode=", r.StatusCode) } } return false }
func del_tx(par string) { txid := btc.NewUint256FromString(par) if txid == nil { fmt.Println("You must specify a valid transaction ID for this command.") list_txs("") return } network.TxMutex.Lock() if _, ok := network.TransactionsToSend[txid.Hash]; !ok { network.TxMutex.Unlock() fmt.Println("No such transaction ID in the memory pool.") list_txs("") return } delete(network.TransactionsToSend, txid.Hash) network.TxMutex.Unlock() fmt.Println("Transaction", txid.String(), "removed from the memory pool") }
func send_tx(par string) { txid := btc.NewUint256FromString(par) if txid == nil { fmt.Println("You must specify a valid transaction ID for this command.") list_txs("") return } network.TxMutex.Lock() if ptx, ok := network.TransactionsToSend[txid.BIdx()]; ok { network.TxMutex.Unlock() cnt := network.NetRouteInv(1, txid, nil) ptx.Invsentcnt += cnt fmt.Println("INV for TxID", txid.String(), "sent to", cnt, "node(s)") fmt.Println("If it does not appear in the chain, you may want to redo it.") } else { network.TxMutex.Unlock() fmt.Println("No such transaction ID in the memory pool.") list_txs("") } }
func send1_tx(par string) { txid := btc.NewUint256FromString(par) if txid == nil { fmt.Println("You must specify a valid transaction ID for this command.") list_txs("") return } network.TxMutex.Lock() if ptx, ok := network.TransactionsToSend[txid.Hash]; ok { network.TxMutex.Unlock() usif.SendInvToRandomPeer(1, txid) ptx.Invsentcnt++ fmt.Println("INV for TxID", txid.String(), "sent to a random node") fmt.Println("If it does not appear in the chain, you may want to redo it.") } else { network.TxMutex.Unlock() fmt.Println("No such transaction ID in the memory pool.") list_txs("") } }
func dump_block(s string) { h := btc.NewUint256FromString(s) if h == nil { println("Specify block's hash") return } bl, _, e := common.BlockChain.Blocks.BlockGet(h) if e != nil { println(e.Error()) return } fn := h.String() + ".bin" f, e := os.Create(fn) if e != nil { println(e.Error()) return } f.Write(bl) f.Close() fmt.Println("Block saved to file:", fn) }
func main() { StartTime = time.Now() GenesisBlock := btc.NewUint256FromString("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f") Magic = [4]byte{0xF9, 0xBE, 0xB4, 0xD9} GocoinHomeDir = "btcnet" + string(os.PathSeparator) BlockChain = btc.NewChain(GocoinHomeDir, GenesisBlock, false) if btc.AbortNow || BlockChain == nil { return } new_connection("129.132.230.71") //new_connection("198.12.127.2") //new_connection("85.17.239.32") //new_connection("94.23.228.130") //new_connection("129.132.230.75") //new_connection("178.63.63.214") get_headers() return }
// load the content of the "balance/" folder func load_balance() { var unknownInputs int f, e := os.Open("balance/unspent.txt") if e != nil { println(e.Error()) os.Exit(1) } rd := bufio.NewReader(f) for { l, _, e := rd.ReadLine() if len(l) == 0 && e != nil { break } if l[64] == '-' { txid := btc.NewUint256FromString(string(l[:64])) rst := strings.SplitN(string(l[65:]), " ", 2) vout, _ := strconv.ParseUint(rst[0], 10, 32) uns := new(btc.TxPrevOut) copy(uns.Hash[:], txid.Hash[:]) uns.Vout = uint32(vout) lab := "" if len(rst) > 1 { lab = rst[1] } if _, ok := loadedTxs[txid.Hash]; !ok { tf, _ := os.Open("balance/" + txid.String() + ".tx") if tf != nil { siz, _ := tf.Seek(0, os.SEEK_END) tf.Seek(0, os.SEEK_SET) buf := make([]byte, siz) tf.Read(buf) tf.Close() th := btc.Sha2Sum(buf) if bytes.Equal(th[:], txid.Hash[:]) { tx, _ := btc.NewTx(buf) if tx != nil { loadedTxs[txid.Hash] = tx } else { println("transaction is corrupt:", txid.String()) } } else { println("transaction file is corrupt:", txid.String()) os.Exit(1) } } else { println("transaction file not found:", txid.String()) os.Exit(1) } } uo := UO(uns) fnd := false for j := range publ_addrs { if publ_addrs[j].Owns(uo.Pk_script) { unspentOuts = append(unspentOuts, uns) unspentOutsLabel = append(unspentOutsLabel, lab) totBtc += UO(uns).Value fnd = true break } } if !fnd { unknownInputs++ if *verbose { fmt.Println(uns.String(), "does not belogn to your wallet - ignore it") } } } } f.Close() fmt.Printf("You have %.8f BTC in %d unspent outputs\n", float64(totBtc)/1e8, len(unspentOuts)) if unknownInputs > 0 { fmt.Printf("WARNING: Some inputs (%d) cannot be spent (-v to print them)\n", unknownInputs) } }
func main() { fmt.Println("Gocoin blockchain downloader version", btc.SourcesTag) parse_command_line() setup_runtime_vars() if !add_ip_str(SeedNode) { println("You need to specify IP address of a fast seed node.") println("For example run it like this: downloader -s 89.31.102.237") return } load_ips() // other seed nodes if len(GocoinHomeDir) > 0 && GocoinHomeDir[len(GocoinHomeDir)-1] != os.PathSeparator { GocoinHomeDir += string(os.PathSeparator) } if Testnet { GocoinHomeDir += "tstnet" + string(os.PathSeparator) Magic = [4]byte{0x0B, 0x11, 0x09, 0x07} DefaultTcpPort = 18333 GenesisBlock = btc.NewUint256FromString("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943") fmt.Println("Using testnet3") } else { GocoinHomeDir += "btcnet" + string(os.PathSeparator) } fmt.Println("GocoinHomeDir:", GocoinHomeDir) utils.LockDatabaseDir(GocoinHomeDir) defer utils.UnlockDatabaseDir() StartTime = time.Now() if open_blockchain() { fmt.Printf("Blockchain opening aborted\n") close_blockchain() return } fmt.Println("Blockchain open in", time.Now().Sub(StartTime)) go do_usif() fmt.Println("Downloading headers from the seed peer", SeedNode) download_headers() if GlobalExit { close_blockchain() return } if DoThePings { fmt.Println("Tuning to other peers and trying to find the fastest ones.") fmt.Println("Execute command 'g' to continue to block chain download.") fmt.Println("Otherwise it will auto-continue after 15 minutes.") usif_prompt() do_pings() fmt.Println("Pings done.") usif_prompt() } var HighestTrustedBlock *btc.Uint256 if LastTrustedBlock == "all" { HighestTrustedBlock = TheBlockChain.BlockTreeEnd.BlockHash fmt.Println("Assume all blocks trusted") } else if LastTrustedBlock == "auto" { if LastBlockHeight > 6 { ha := BlocksToGet[LastBlockHeight] HighestTrustedBlock = btc.NewUint256(ha[:]) fmt.Println("Assume last trusted block as", HighestTrustedBlock.String()) } else { fmt.Println("-t=auto ignored since LastBlockHeight is only", LastBlockHeight) } } else if LastTrustedBlock != "" { HighestTrustedBlock = btc.NewUint256FromString(LastTrustedBlock) } if HighestTrustedBlock != nil { for k, h := range BlocksToGet { if bytes.Equal(h[:], HighestTrustedBlock.Hash[:]) { TrustUpTo = k fmt.Println("All the blocks up to", TrustUpTo, "are assumed trusted") break } } } else { fmt.Println("None of the blocks is to be assumed trusted (it will be very slow).") } for n := TheBlockChain.BlockTreeEnd; n != nil && n.Height > TheBlockChain.BlockTreeEnd.Height-BSLEN; n = n.Parent { blocksize_update(int(n.BlockSize)) } fmt.Println("Downloading blocks - BlocksToGet:", len(BlocksToGet), " avg_size:", avg_block_size()) usif_prompt() StartTime = time.Now() get_blocks() fmt.Println("Up to block", TheBlockChain.BlockTreeEnd.Height, "in", time.Now().Sub(StartTime).String()) close_all_connections() close_blockchain() return }
"os" "os/signal" "runtime" "runtime/debug" "time" //"github.com/piotrnar/gocoin/qdb" "github.com/piotrnar/gocoin/btc/qdb" "github.com/piotrnar/gocoin/tools/utils" ) var ( Magic [4]byte = [4]byte{0xF9, 0xBE, 0xB4, 0xD9} StartTime time.Time TheBlockChain *btc.Chain GenesisBlock *btc.Uint256 = btc.NewUint256FromString("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f") TrustUpTo uint32 GlobalExit bool // CommandLineSwitches LastTrustedBlock string // -trust GocoinHomeDir string // -d OnlyStoreBlocks bool // -b MaxNetworkConns uint // -n GCPerc int // -g SeedNode string // -s DoThePings bool // -p MemForBlocks uint // -m (in megabytes) Testnet bool // -t )
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) }
// load the content of the "balance/" folder func load_balance(showbalance bool) { var unknownInputs, multisigInputs int f, e := os.Open("balance/unspent.txt") if e != nil { println(e.Error()) return } rd := bufio.NewReader(f) for { l, _, e := rd.ReadLine() if len(l) == 0 && e != nil { break } if l[64] == '-' { txid := btc.NewUint256FromString(string(l[:64])) rst := strings.SplitN(string(l[65:]), " ", 2) vout, _ := strconv.ParseUint(rst[0], 10, 32) uns := new(btc.TxPrevOut) copy(uns.Hash[:], txid.Hash[:]) uns.Vout = uint32(vout) lab := "" if len(rst) > 1 { lab = rst[1] } str := string(l) if sti := strings.Index(str, "_StealthC:"); sti != -1 { c, e := hex.DecodeString(str[sti+10 : sti+10+64]) if e != nil { fmt.Println("ERROR at stealth", txid.String(), vout, e.Error()) } else { // add a new key to the wallet sec := btc.DeriveNextPrivate(first_seed[:], c) is_stealth[len(priv_keys)] = true priv_keys = append(priv_keys, sec) labels = append(labels, lab) pub_key := btc.PublicFromPrivate(sec, true) publ_addrs = append(publ_addrs, btc.NewAddrFromPubkey(pub_key, btc.AddrVerPubkey(*testnet))) compressed_key = append(compressed_key, true) // stealth keys are always compressed } } if _, ok := loadedTxs[txid.Hash]; !ok { tf, _ := os.Open("balance/" + txid.String() + ".tx") if tf != nil { siz, _ := tf.Seek(0, os.SEEK_END) tf.Seek(0, os.SEEK_SET) buf := make([]byte, siz) tf.Read(buf) tf.Close() th := btc.Sha2Sum(buf) if bytes.Equal(th[:], txid.Hash[:]) { tx, _ := btc.NewTx(buf) if tx != nil { loadedTxs[txid.Hash] = tx } else { println("transaction is corrupt:", txid.String()) } } else { println("transaction file is corrupt:", txid.String()) os.Exit(1) } } else { println("transaction file not found:", txid.String()) os.Exit(1) } } // Sum up all the balance and check if we have private key for this input uo := UO(uns) add_it := true if !btc.IsP2SH(uo.Pk_script) { fnd := false for j := range publ_addrs { if publ_addrs[j].Owns(uo.Pk_script) { fnd = true break } } if !fnd { if *onlvalid { add_it = false } if showbalance { unknownInputs++ if *verbose { ss := uns.String() ss = ss[:8] + "..." + ss[len(ss)-12:] fmt.Println(ss, "does not belong to your wallet (cannot sign it)") } } } } else { if *onlvalid { add_it = false } if *verbose { ss := uns.String() ss = ss[:8] + "..." + ss[len(ss)-12:] fmt.Println(ss, "belongs to a multisig address") } multisigInputs++ } if add_it { unspentOuts = append(unspentOuts, uns) unspentOutsLabel = append(unspentOutsLabel, lab) totBtc += UO(uns).Value } } } f.Close() fmt.Printf("You have %.8f BTC in %d unspent outputs. %d inputs are multisig type\n", float64(totBtc)/1e8, len(unspentOuts), multisigInputs) if showbalance { if unknownInputs > 0 { fmt.Printf("WARNING: Some inputs (%d) cannot be spent with this password (-v to print them)\n", unknownInputs) } } }
"time" //"github.com/piotrnar/gocoin/qdb" "github.com/piotrnar/gocoin/btc/qdb" "github.com/piotrnar/gocoin/tools/utils" ) const ( TheGenesis = "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f" ) var ( Magic [4]byte = [4]byte{0xF9, 0xBE, 0xB4, 0xD9} StartTime time.Time TheBlockChain *btc.Chain GenesisBlock *btc.Uint256 = btc.NewUint256FromString(TheGenesis) TrustUpTo uint32 GlobalExit bool // CommandLineSwitches LastTrustedBlock string // -t GocoinHomeDir string // -d OnlyStoreBlocks bool // -b MaxNetworkConns uint // -n GCPerc int // -g SeedNode string // -s DoThePings bool // -p MemForBlocks uint // -m (in megabytes) ) func parse_command_line() {
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) }
// load the content of the "balance/" folder func load_balance(showbalance bool) { var unknownInputs, multisigInputs int f, e := os.Open("balance/unspent.txt") if e != nil { println(e.Error()) return } rd := bufio.NewReader(f) for { l, _, e := rd.ReadLine() if len(l) == 0 && e != nil { break } if l[64] == '-' { txid := btc.NewUint256FromString(string(l[:64])) rst := strings.SplitN(string(l[65:]), " ", 2) vout, _ := strconv.ParseUint(rst[0], 10, 32) uns := new(btc.TxPrevOut) copy(uns.Hash[:], txid.Hash[:]) uns.Vout = uint32(vout) lab := "" if len(rst) > 1 { lab = rst[1] } if _, ok := loadedTxs[txid.Hash]; !ok { tf, _ := os.Open("balance/" + txid.String() + ".tx") if tf != nil { siz, _ := tf.Seek(0, os.SEEK_END) tf.Seek(0, os.SEEK_SET) buf := make([]byte, siz) tf.Read(buf) tf.Close() th := btc.Sha2Sum(buf) if bytes.Equal(th[:], txid.Hash[:]) { tx, _ := btc.NewTx(buf) if tx != nil { loadedTxs[txid.Hash] = tx } else { println("transaction is corrupt:", txid.String()) } } else { println("transaction file is corrupt:", txid.String()) os.Exit(1) } } else { println("transaction file not found:", txid.String()) os.Exit(1) } } unspentOuts = append(unspentOuts, uns) unspentOutsLabel = append(unspentOutsLabel, lab) // Sum up all the balance and check if we have private key for this input uo := UO(uns) totBtc += UO(uns).Value if !btc.IsP2SH(uo.Pk_script) { fnd := false for j := range publ_addrs { if publ_addrs[j].Owns(uo.Pk_script) { fnd = true break } } if showbalance && !fnd { unknownInputs++ if *verbose { ss := uns.String() ss = ss[:8] + "..." + ss[len(ss)-12:] fmt.Println(ss, "does not belong to your wallet (cannot sign it)") } } } else { if *verbose { ss := uns.String() ss = ss[:8] + "..." + ss[len(ss)-12:] fmt.Println(ss, "belongs to a multisig address") } multisigInputs++ } } } f.Close() fmt.Printf("You have %.8f BTC in %d unspent outputs. %d inputs are multisig type\n", float64(totBtc)/1e8, len(unspentOuts), multisigInputs) if showbalance { if unknownInputs > 0 { fmt.Printf("WARNING: Some inputs (%d) cannot be spent with this password (-v to print them)\n", unknownInputs) } } }
func main() { if len(os.Args) < 2 { fmt.Println("Specify at least one parameter - a path to the blk0000?.dat files.") fmt.Println("By default it should be:", utils.BitcoinHome()+"blocks") fmt.Println() fmt.Println("If you specify a second parameter, that's where output data will be stored.") fmt.Println("Otherwise the output data will go to Gocoin's default data folder.") return } BtcRootDir = RemoveLastSlash(os.Args[1]) fn := BtcRootDir + string(os.PathSeparator) + "blk00000.dat" fmt.Println("Looking for file", fn, "...") f, e := os.Open(fn) if e != nil { println(e.Error()) os.Exit(1) } _, e = f.Read(Magic[:]) f.Close() if e != nil { println(e.Error()) os.Exit(1) } if len(os.Args) > 2 { GocoinHomeDir = RemoveLastSlash(os.Args[2]) + string(os.PathSeparator) } else { GocoinHomeDir = utils.BitcoinHome() + "gocoin" + string(os.PathSeparator) } if Magic == [4]byte{0x0B, 0x11, 0x09, 0x07} { // testnet3 fmt.Println("There are Testnet3 blocks") GenesisBlock = btc.NewUint256FromString("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943") GocoinHomeDir += "tstnet" + string(os.PathSeparator) } else if Magic == [4]byte{0xF9, 0xBE, 0xB4, 0xD9} { fmt.Println("There are valid Bitcoin blocks") GenesisBlock = btc.NewUint256FromString("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f") GocoinHomeDir += "btcnet" + string(os.PathSeparator) } else { println("blk00000.dat has an unexpected magic") os.Exit(1) } fmt.Println("Importing blockchain data into", GocoinHomeDir, "...") if exists(GocoinHomeDir+"blockchain.dat") || exists(GocoinHomeDir+"blockchain.idx") || exists(GocoinHomeDir+"unspent") { println("Destination folder contains some database files.") println("Either move them somewhere else or delete manually.") println("None of the following files/folders must exist before you proceed:") println(" *", GocoinHomeDir+"blockchain.dat") println(" *", GocoinHomeDir+"blockchain.idx") println(" *", GocoinHomeDir+"unspent") os.Exit(1) } import_blockchain(BtcRootDir) }
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 host_init() { var e error BtcRootDir := utils.BitcoinHome() if common.CFG.Datadir == "" { common.GocoinHomeDir = BtcRootDir + "gocoin" + string(os.PathSeparator) } else { common.GocoinHomeDir = common.CFG.Datadir + string(os.PathSeparator) } if common.CFG.Testnet { // testnet3 common.GenesisBlock = btc.NewUint256FromString("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943") common.Magic = [4]byte{0x0B, 0x11, 0x09, 0x07} common.GocoinHomeDir += "tstnet" + string(os.PathSeparator) common.AddrVersion = 0x6f BtcRootDir += "testnet3" + string(os.PathSeparator) network.AlertPubKey, _ = hex.DecodeString("04302390343f91cc401d56d68b123028bf52e5fca1939df127f63c6467cdf9c8e2c14b61104cf817d0b780da337893ecc4aaff1309e536162dabbdb45200ca2b0a") common.MaxPeersNeeded = 100 } else { common.GenesisBlock = btc.NewUint256FromString("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f") common.Magic = [4]byte{0xF9, 0xBE, 0xB4, 0xD9} common.GocoinHomeDir += "btcnet" + string(os.PathSeparator) common.AddrVersion = 0x00 network.AlertPubKey, _ = hex.DecodeString("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284") common.MaxPeersNeeded = 1000 } // Lock the folder os.MkdirAll(common.GocoinHomeDir, 0770) os.MkdirAll(common.GocoinHomeDir+"wallet", 0770) LockDatabaseDir() fi, e := os.Stat(common.GocoinHomeDir + "blockchain.idx") if e != nil { os.RemoveAll(common.GocoinHomeDir) fmt.Println("You seem to be running Gocoin for the fist time on this PC") fi, e = os.Stat(BtcRootDir + "blocks/blk00000.dat") if e == nil && fi.Size() > 1024*1024 { fmt.Println("There is a database from Satoshi client on your disk...") if textui.AskYesNo("Do you want to import this database into Gocoin?") { import_blockchain(BtcRootDir + "blocks") } } } fmt.Println("Opening blockchain... (Ctrl-C to interrupt)") __exit := make(chan bool) __done := make(chan bool) go func() { for { select { case s := <-killchan: fmt.Println(s) btc.AbortNow = true case <-__exit: __done <- true return } } }() sta := time.Now().UnixNano() common.BlockChain = btc.NewChain(common.GocoinHomeDir, common.GenesisBlock, common.FLAG.Rescan) sto := time.Now().UnixNano() if btc.AbortNow { fmt.Printf("Blockchain opening aborted after %.3f seconds\n", float64(sto-sta)/1e9) UnlockDatabaseDir() os.Exit(1) } fmt.Printf("Blockchain open in %.3f seconds\n", float64(sto-sta)/1e9) common.BlockChain.Unspent.SetTxNotify(wallet.TxNotify) common.StartTime = time.Now() __exit <- true _ = <-__done }
// Download (and re-assemble) raw transaction from blockexplorer.com func GetTxFromExplorer(txid *btc.Uint256) ([]byte, []byte) { url := "http://blockexplorer.com/rawtx/" + txid.String() r, er := http.Get(url) if er == nil && r.StatusCode == 200 { defer r.Body.Close() c, _ := ioutil.ReadAll(r.Body) var txx onetx er = json.Unmarshal(c[:], &txx) if er == nil { // This part looks weird, but this is how I solved seq=FFFFFFFF, if the field not present: for i := range txx.In { txx.In[i].Sequence = 0xffffffff } json.Unmarshal(c[:], &txx) // ... end of the weird solution tx := new(btc.Tx) tx.Version = txx.Ver tx.TxIn = make([]*btc.TxIn, len(txx.In)) for i := range txx.In { tx.TxIn[i] = new(btc.TxIn) tx.TxIn[i].Input.Hash = btc.NewUint256FromString(txx.In[i].Prev_out.Hash).Hash tx.TxIn[i].Input.Vout = txx.In[i].Prev_out.N if txx.In[i].Prev_out.N == 0xffffffff && txx.In[i].Prev_out.Hash == "0000000000000000000000000000000000000000000000000000000000000000" { tx.TxIn[i].ScriptSig, _ = hex.DecodeString(txx.In[i].Coinbase) } else { tx.TxIn[i].ScriptSig, _ = btc.DecodeScript(txx.In[i].ScriptSig) } tx.TxIn[i].Sequence = txx.In[i].Sequence } tx.TxOut = make([]*btc.TxOut, len(txx.Out)) for i := range txx.Out { am, er := btc.StringToSatoshis(txx.Out[i].Value) if er != nil { fmt.Println("Incorrect BTC amount", txx.Out[i].Value, er.Error()) return nil, nil } tx.TxOut[i] = new(btc.TxOut) tx.TxOut[i].Value = am tx.TxOut[i].Pk_script, _ = btc.DecodeScript(txx.Out[i].ScriptPubKey) } tx.Lock_time = txx.Lock_time rawtx := tx.Serialize() if txx.Size != uint(len(rawtx)) { fmt.Printf("Transaction size mismatch: %d expexted, %d decoded\n", txx.Size, len(rawtx)) return nil, rawtx } curid := btc.NewSha2Hash(rawtx) if !curid.Equal(txid) { fmt.Println("The downloaded transaction does not match its ID.", txid.String()) return nil, rawtx } return rawtx, rawtx } else { fmt.Println("json.Unmarshal:", er.Error()) } } else { if er != nil { fmt.Println("http.Get:", er.Error()) } else { fmt.Println("StatusCode=", r.StatusCode) } } return nil, nil }