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

	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.BIdx()]; ok {
		s, _, _, _, _ := usif.DecodeTx(tx.Tx)
		w.Write([]byte(s))
	} else {
		fmt.Fprintln(w, "Not found")
	}
}
Example #2
0
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 := script.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>")
				ads := "???"
				if ad := btc.NewAddrFromPkScript(po.Pk_script, common.Testnet); ad != nil {
					ads = ad.String()
				}
				fmt.Fprint(w, "<addr>", ads, "</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>"))
}
Example #3
0
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.BIdx()]; ok {
		s, _, _, _, _ := usif.DecodeTx(tx.Tx)
		fmt.Println(s)
	} else {
		fmt.Println("No such transaction ID in the memory pool.")
	}
}
Example #4
0
func main() {
	fmt.Println("Gocoin FetchTx version", lib.Version)

	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)
	}
}
Example #5
0
func parserec(vv []interface{}) (ret *testvector) {
	ret = new(testvector)
	for i, u := range vv[0].([]interface{}) {
		switch uu := u.(type) {
		case []interface{}:
			txid := btc.NewUint256FromString(uu[0].(string))
			ret.inps = append(ret.inps, oneinp{txid: txid,
				vout: int(uu[1].(float64)), pkscr: uu[2].(string)})
		default:
			fmt.Printf(" - %d is of a type %T\n", i, uu)
		}
	}
	ret.tx = vv[1].(string)
	params := vv[2].(string)
	ret.p2sh = strings.Index(params, "P2SH") != -1
	ret.nulldummy = strings.Index(params, "NULLDUMMY") != -1
	return
}
Example #6
0
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.BIdx()]; !ok {
		network.TxMutex.Unlock()
		fmt.Println("No such transaction ID in the memory pool.")
		list_txs("")
		return
	}
	delete(network.TransactionsToSend, txid.BIdx())
	network.TxMutex.Unlock()
	fmt.Println("Transaction", txid.String(), "removed from the memory pool")
}
Example #7
0
func NewUnspRec(l []byte) (uns *unspRec) {
	if l[64] != '-' {
		return nil
	}

	txid := btc.NewUint256FromString(string(l[:64]))
	if txid == nil {
		return nil
	}

	rst := strings.SplitN(string(l[65:]), " ", 2)
	vout, e := strconv.ParseUint(rst[0], 10, 32)
	if e != nil {
		return nil
	}

	uns = new(unspRec)
	uns.TxPrevOut.Hash = txid.Hash
	uns.TxPrevOut.Vout = uint32(vout)
	if len(rst) > 1 {
		uns.label = rst[1]
	}

	if first_determ_idx < len(keys) {
		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(keys[first_determ_idx].Key, c)
				rec := btc.NewPrivateAddr(sec, ver_secret(), true) // stealth keys are always compressed
				rec.BtcAddr.Extra.Label = uns.label
				keys = append(keys, rec)
				uns.stealth = true
				uns.key = rec
			}
		}
	}

	return
}
Example #8
0
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.BIdx()]; 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("")
	}
}
Example #9
0
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)
}
Example #10
0
func TestSighash(t *testing.T) {
	var arr [][]interface{}

	dat, er := ioutil.ReadFile("../test/sighash.json")
	if er != nil {
		println(er.Error())
		return
	}

	r := bytes.NewBuffer(dat)
	d := json.NewDecoder(r)
	d.UseNumber()

	er = d.Decode(&arr)
	if er != nil {
		println(er.Error())
		return
	}
	for i := range arr {
		if len(arr[i]) == 5 {
			tmp, _ := hex.DecodeString(arr[i][0].(string))
			tx, _ := btc.NewTx(tmp)
			if tx == nil {
				t.Error("Cannot decode tx from text number", i)
				continue
			}
			tmp, _ = hex.DecodeString(arr[i][1].(string)) // script
			iidx, _ := arr[i][2].(json.Number).Int64()
			htype, _ := arr[i][3].(json.Number).Int64()
			got := tx.SignatureHash(tmp, int(iidx), int32(htype))
			exp := btc.NewUint256FromString(arr[i][4].(string))
			if !bytes.Equal(exp.Hash[:], got) {
				t.Error("SignatureHash mismatch at index", i)
			}
		}
	}
}
Example #11
0
func host_init() {
	var e error
	BtcRootDir := sys.BitcoinHome()

	if common.CFG.Datadir == "" {
		common.GocoinHomeDir = BtcRootDir + "gocoin" + string(os.PathSeparator)
	} else {
		common.GocoinHomeDir = common.CFG.Datadir + string(os.PathSeparator)
	}

	common.Testnet = common.CFG.Testnet // So chaging this value would will only affect the behaviour after restart
	if common.CFG.Testnet {             // testnet3
		common.GenesisBlock = btc.NewUint256FromString("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943")
		common.Magic = [4]byte{0x0B, 0x11, 0x09, 0x07}
		common.GocoinHomeDir += "tstnet" + string(os.PathSeparator)
		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)
		network.AlertPubKey, _ = hex.DecodeString("04fc9702847840aaf195de8442ebecedf5b095cdbb9bc716bda9110971b28a49e0ead8564ff0db22209e0374782c093bb899692d524e9d6a6956e7c5ecbcd68284")
		common.MaxPeersNeeded = 1000
	}

	// Lock the folder
	os.MkdirAll(common.GocoinHomeDir, 0770)
	os.MkdirAll(common.GocoinHomeDir+"wallet", 0770)
	sys.LockDatabaseDir(common.GocoinHomeDir)

	fi, e := os.Stat(common.GocoinHomeDir + "blockchain.dat")
	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")
			}
		}
	}

	// Create default wallet file if does not exist
	default_wallet_fn := common.GocoinHomeDir + "wallet" + string(os.PathSeparator) + wallet.DefaultFileName
	fi, _ = os.Stat(default_wallet_fn)
	if fi == nil || fi.IsDir() {
		fmt.Println(default_wallet_fn, "not found")

		old_wallet_location := common.GocoinHomeDir + "wallet.txt"
		// If there is wallet.txt rename it to default.
		fi, _ := os.Stat(old_wallet_location)
		if fi != nil && !fi.IsDir() {
			fmt.Println("Taking wallet.txt as", default_wallet_fn)
			os.Rename(old_wallet_location, default_wallet_fn)
		} else {
			fmt.Println("Creating empty default wallet at", default_wallet_fn)
			ioutil.WriteFile(default_wallet_fn, []byte(fmt.Sprintln("# Put your wallet's public addresses here")), 0660)
		}
	}

	// cache the current balance of all the addresses from the current wallet files
	wallet.LoadAllWallets()

	fmt.Println("Loading UTXO database while checking balance of", len(wallet.MyWallet.Addrs),
		"addresses... (press Ctrl-C to interrupt)")

	__exit := make(chan bool)
	__done := make(chan bool)
	go func() {
		for {
			select {
			case s := <-killchan:
				fmt.Println(s)
				chain.AbortNow = true
			case <-__exit:
				__done <- true
				return
			}
		}
	}()

	ext := &chain.NewChanOpts{NotifyTxAdd: wallet.TxNotifyAdd,
		NotifyTxDel: wallet.TxNotifyDel, LoadWalk: wallet.NewUTXO}

	sta := time.Now().UnixNano()
	common.BlockChain = chain.NewChainExt(common.GocoinHomeDir, common.GenesisBlock, common.FLAG.Rescan, ext)
	sto := time.Now().UnixNano()
	if chain.AbortNow {
		fmt.Printf("Blockchain opening aborted after %.3f seconds\n", float64(sto-sta)/1e9)
		common.BlockChain.Close()
		sys.UnlockDatabaseDir()
		os.Exit(1)
	}
	wallet.ChainInitDone()
	al, sy := sys.MemUsed()
	fmt.Printf("Blockchain open in %.3f seconds.  %d + %d MB of RAM used (%d)\n",
		float64(sto-sta)/1e9, al>>20, qdb.ExtraMemoryConsumed>>20, sy>>20)
	common.StartTime = time.Now()
	__exit <- true
	_ = <-__done

	// ... and now load the dafault wallet
	wallet.LoadWallet(default_wallet_fn)
	if wallet.MyWallet != nil {
		wallet.UpdateBalance()
		fmt.Print(wallet.DumpBalance(wallet.MyBalance, nil, false, true))
	}
}
Example #12
0
// 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
}
Example #13
0
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:", sys.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 = sys.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)
}
Example #14
0
	"github.com/niniwzw/gocoin/lib/others/sys"
	"github.com/niniwzw/gocoin/lib/qdb"
	"os"
	"os/signal"
	"runtime"
	"runtime/debug"
	"sync/atomic"
	"time"
)

var (
	Magic         [4]byte = [4]byte{0xF9, 0xBE, 0xB4, 0xD9}
	StartTime     time.Time
	TheBlockChain *chain.Chain

	GenesisBlock *btc.Uint256 = btc.NewUint256FromString("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f")
	TrustUpTo    uint32
	globalexit   uint32

	// CommandLineSwitches
	LastTrustedBlock string // -trust
	GocoinHomeDir    string // -d
	OnlyStoreBlocks  bool   // -b
	MaxNetworkConns  uint   // -n
	GCPerc           int    // -g
	SeedNode         string // -s
	MemForBlocks     uint   // -m (in megabytes)
	Testnet          bool   // -t
)

func GlobalExit() bool {
Example #15
0
func xml_txs2s(w http.ResponseWriter, r *http.Request) {
	if !ipchecker(r) {
		return
	}

	if checksid(r) {
		if len(r.Form["del"]) > 0 {
			tid := btc.NewUint256FromString(r.Form["del"][0])
			if tid != nil {
				network.TxMutex.Lock()
				delete(network.TransactionsToSend, tid.BIdx())
				network.TxMutex.Unlock()
			}
		}

		if len(r.Form["send"]) > 0 {
			tid := btc.NewUint256FromString(r.Form["send"][0])
			if tid != nil {
				network.TxMutex.Lock()
				if ptx, ok := network.TransactionsToSend[tid.BIdx()]; ok {
					network.TxMutex.Unlock()
					cnt := network.NetRouteInv(1, tid, nil)
					if cnt == 0 {
						usif.SendInvToRandomPeer(1, tid)
					} else {
						ptx.Invsentcnt += cnt
					}
				} else {
					network.TxMutex.Unlock()
				}
			}
		}

		if len(r.Form["sendone"]) > 0 {
			tid := btc.NewUint256FromString(r.Form["sendone"][0])
			if tid != nil {
				network.TxMutex.Lock()
				if ptx, ok := network.TransactionsToSend[tid.BIdx()]; ok {
					network.TxMutex.Unlock()
					usif.SendInvToRandomPeer(1, tid)
					ptx.Invsentcnt++
				} else {
					network.TxMutex.Unlock()
				}
			}
		}

	}

	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 _, v := range network.TransactionsToSend {
		w.Write([]byte("<tx>"))
		fmt.Fprint(w, "<id>", v.Tx.Hash.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>"))
}
Example #16
0
func main() {
	fmt.Println("Gocoin blockchain downloader version", lib.Version)
	parse_command_line()
	setup_runtime_vars()

	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}
		GenesisBlock = btc.NewUint256FromString("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943")
		fmt.Println("Using testnet3")
	} else {
		GocoinHomeDir += "btcnet" + string(os.PathSeparator)
	}
	fmt.Println("GocoinHomeDir:", GocoinHomeDir)

	sys.LockDatabaseDir(GocoinHomeDir)
	defer sys.UnlockDatabaseDir()

	peersdb.Testnet = Testnet
	peersdb.InitPeers(GocoinHomeDir)

	StartTime = time.Now()
	if open_blockchain() {
		fmt.Printf("Blockchain opening aborted\n")
		return
	}
	fmt.Println("Blockchain open in", time.Now().Sub(StartTime))

	go do_usif()

	download_headers()
	if GlobalExit() {
		TheBlockChain.Close()
		return
	}

	var HighestTrustedBlock *btc.Uint256
	if LastTrustedBlock == "all" {
		HighestTrustedBlock = TheBlockChain.BlockTreeEnd.BlockHash
		fmt.Println("Assume all blocks trusted")
	} else if LastTrustedBlock == "auto" {
		if LastBlockHeight > 6 {
			use := LastBlockHeight - 6
			ha := BlocksToGet[use]
			HighestTrustedBlock = btc.NewUint256(ha[:])
			fmt.Println("Assume last trusted block as", HighestTrustedBlock.String(), "at", use)
		} 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
				break
			}
		}
	} else {
		fmt.Println("WARNING: The trusted block not found (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()

	peersdb.ClosePeerDB()

	StartTime = time.Now()
	fmt.Print("All blocks done - defrag unspent")
	qdb.SetDefragPercent(100)
	for {
		if !TheBlockChain.Unspent.Idle() {
			break
		}
		fmt.Print(".")
	}
	fmt.Println("\nDefrag unspent done in", time.Now().Sub(StartTime).String())
	TheBlockChain.Close()

	return
}
Example #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 chain.AllUnspentTx
		var pay_cmd string
		var totalinput, spentsofar uint64
		var change_addr *btc.BtcAddr
		var multisig_input []*wallet.MultisigAddr

		addrs_to_msign := make(map[string]bool)

		tx := new(btc.Tx)
		tx.Version = 1
		tx.Lock_time = 0

		outcnt, _ := strconv.ParseUint(r.Form["outcnt"][0], 10, 32)

		wallet.BalanceMutex.Lock()
		for i := 1; i <= int(outcnt); i++ {
			is := fmt.Sprint(i)
			if len(r.Form["txout"+is]) == 1 && r.Form["txout"+is][0] == "on" {
				hash := btc.NewUint256FromString(r.Form["txid"+is][0])
				if hash != nil {
					vout, er := strconv.ParseUint(r.Form["txvout"+is][0], 10, 32)
					if er == nil {
						var po = btc.TxPrevOut{Hash: hash.Hash, Vout: uint32(vout)}
						for j := range wallet.MyBalance {
							if wallet.MyBalance[j].TxPrevOut == po {
								thisbal = append(thisbal, wallet.MyBalance[j])

								// Add the input to our tx
								tin := new(btc.TxIn)
								tin.Input = wallet.MyBalance[j].TxPrevOut
								tin.Sequence = 0xffffffff
								tx.TxIn = append(tx.TxIn, tin)

								// Add new multisig address description
								_, msi := wallet.IsMultisig(wallet.MyBalance[j].BtcAddr)
								multisig_input = append(multisig_input, msi)
								if msi != nil {
									for ai := range msi.ListOfAddres {
										addrs_to_msign[msi.ListOfAddres[ai]] = true
									}
								}

								// Add the value to total input value
								totalinput += wallet.MyBalance[j].Value

								// If no change specified, use the first input addr as it
								if change_addr == nil {
									change_addr = wallet.MyBalance[j].BtcAddr
								}
							}
						}
					}
				}
			}
		}
		wallet.BalanceMutex.Unlock()

		for i := 1; ; i++ {
			adridx := fmt.Sprint("adr", i)
			btcidx := fmt.Sprint("btc", i)

			if len(r.Form[adridx]) != 1 || len(r.Form[btcidx]) != 1 {
				break
			}

			if len(r.Form[adridx][0]) > 1 {
				addr, er := btc.NewAddrFromString(r.Form[adridx][0])
				if er == nil {
					am, er := btc.StringToSatoshis(r.Form[btcidx][0])
					if er == nil && am > 0 {
						if pay_cmd == "" {
							pay_cmd = "wallet -useallinputs -send "
						} else {
							pay_cmd += ","
						}
						pay_cmd += addr.Enc58str + "=" + btc.UintToBtc(am)

						outs, er := btc.NewSpendOutputs(addr, am, common.CFG.Testnet)
						if er != nil {
							err = er.Error()
							goto error
						}
						tx.TxOut = append(tx.TxOut, outs...)

						spentsofar += am
					} else {
						err = "Incorrect amount (" + r.Form[btcidx][0] + ") for Output #" + fmt.Sprint(i)
						goto error
					}
				} else {
					err = "Incorrect address (" + r.Form[adridx][0] + ") for Output #" + fmt.Sprint(i)
					goto error
				}
			}
		}

		if pay_cmd == "" {
			err = "No inputs selected"
			goto error
		}

		am, er := btc.StringToSatoshis(r.Form["txfee"][0])
		if er != nil {
			err = "Incorrect fee value: " + r.Form["txfee"][0]
			goto error
		}

		pay_cmd += " -fee " + r.Form["txfee"][0]
		spentsofar += am

		if len(r.Form["change"][0]) > 1 {
			addr, er := btc.NewAddrFromString(r.Form["change"][0])
			if er != nil {
				err = "Incorrect change address: " + r.Form["change"][0]
				goto error
			}
			change_addr = addr
		}
		pay_cmd += " -change " + change_addr.String()

		if totalinput > spentsofar {
			// Add change output
			outs, er := btc.NewSpendOutputs(change_addr, totalinput-spentsofar, common.CFG.Testnet)
			if er != nil {
				err = er.Error()
				goto error
			}
			tx.TxOut = append(tx.TxOut, outs...)
		}

		buf := new(bytes.Buffer)
		zi := zip.NewWriter(buf)

		was_tx := make(map[[32]byte]bool, len(thisbal))
		for i := range thisbal {
			if was_tx[thisbal[i].TxPrevOut.Hash] {
				continue
			}
			was_tx[thisbal[i].TxPrevOut.Hash] = true
			txid := btc.NewUint256(thisbal[i].TxPrevOut.Hash[:])
			fz, _ := zi.Create("balance/" + txid.String() + ".tx")
			wallet.GetRawTransaction(thisbal[i].MinedAt, txid, fz)
		}

		fz, _ := zi.Create("balance/unspent.txt")
		for i := range thisbal {
			fmt.Fprintln(fz, thisbal[i].UnspentTextLine())
		}

		if len(addrs_to_msign) > 0 {
			// Multisig (or mixed) transaction ...
			for i := range multisig_input {
				if multisig_input[i] == nil {
					continue
				}
				d, er := hex.DecodeString(multisig_input[i].RedeemScript)
				if er != nil {
					println("ERROR parsing hex RedeemScript:", er.Error())
					continue
				}
				ms, er := btc.NewMultiSigFromP2SH(d)
				if er != nil {
					println("ERROR parsing bin RedeemScript:", er.Error())
					continue
				}
				tx.TxIn[i].ScriptSig = ms.Bytes()
			}
			fz, _ = zi.Create("multi_" + common.CFG.PayCommandName)
			fmt.Fprintln(fz, "wallet -raw tx2sign.txt")
			for k, _ := range addrs_to_msign {
				fmt.Fprintln(fz, "wallet -msign", k, "-raw ...")
			}
		} else {
			if pay_cmd != "" {
				fz, _ = zi.Create(common.CFG.PayCommandName)
				fz.Write([]byte(pay_cmd))
			}
		}

		// Non-multisig transaction ...
		fz, _ = zi.Create("tx2sign.txt")
		fz.Write([]byte(hex.EncodeToString(tx.Serialize())))

		zi.Close()
		w.Header()["Content-Type"] = []string{"application/zip"}
		w.Write(buf.Bytes())
		return
	} else {
		err = "Bad request"
	}
error:
	s := load_template("send_error.html")
	write_html_head(w, r)
	s = strings.Replace(s, "<!--ERROR_MSG-->", err, 1)
	w.Write([]byte(s))
	write_html_tail(w)
}