コード例 #1
0
ファイル: txs.go プロジェクト: bityuan/gocoin
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")
	}
}
コード例 #2
0
ファイル: txs.go プロジェクト: piotrnar/gocoin
func output_utxo_tx_xml(w http.ResponseWriter, minedid, minedat string) {
	txid := btc.NewUint256FromString(minedid)
	if txid == nil {
		return
	}

	block_number, er := strconv.ParseUint(minedat, 10, 32)
	if er != nil {
		return
	}

	lck := new(usif.OneLock)
	lck.In.Add(1)
	lck.Out.Add(1)
	usif.LocksChan <- lck
	lck.In.Wait()

	w.Write([]byte("<tx>"))
	fmt.Fprint(w, "<id>", minedid, "</id>")
	if dat, er := common.BlockChain.GetRawTx(uint32(block_number), txid); er == nil {
		w.Write([]byte("<status>OK</status>"))
		w.Write([]byte(fmt.Sprint("<size>", len(dat), "</size>")))
		tx, _ := btc.NewTx(dat)
		output_tx_xml(w, tx)
	} else {
		w.Write([]byte("<status>Not found</status>"))
	}
	w.Write([]byte("</tx>"))

	lck.Out.Done()

}
コード例 #3
0
ファイル: tx_test.go プロジェクト: piotrnar/gocoin
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))
			newrec := oneinp{txid: txid, vout: int(uu[1].(float64)), pkscr: uu[2].(string)}
			if len(uu) > 3 {
				newrec.value = uint64(uu[3].(float64))
			}
			ret.inps = append(ret.inps, newrec)
		default:
			fmt.Printf(" - %d is of a type %T\n", i, uu)
		}
	}
	ret.tx = vv[1].(string)
	params := vv[2].(string)
	var e error
	ret.ver_flags, e = decode_flags(params) // deifned in script_test.go
	if e != nil {
		println("skip", params)
		ret.skip = e.Error()
	}
	return
}
コード例 #4
0
ファイル: txs.go プロジェクト: liudch/gocoin
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>"))
		w.Write([]byte(fmt.Sprint("<len>", len(t2s.Data), "</len>")))
		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, script.VER_P2SH|script.VER_DERSIG)
				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>"))
}
コード例 #5
0
ファイル: txcmds.go プロジェクト: piotrnar/gocoin
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.")
	}
}
コード例 #6
0
ファイル: txcmds.go プロジェクト: piotrnar/gocoin
func save_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 {
		fn := tx.Hash.String() + ".tx"
		ioutil.WriteFile(fn, tx.Data, 0600)
		fmt.Println("Saved to", fn)
	} else {
		fmt.Println("No such transaction ID in the memory pool.")
	}
}
コード例 #7
0
ファイル: fetchtx.go プロジェクト: piotrnar/gocoin
func main() {
	fmt.Println("Gocoin FetchTx version", gocoin.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)
	}
}
コード例 #8
0
ファイル: tx_test.go プロジェクト: vancsj/gocoin
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)
	ret.p2sh = vv[2].(bool)
	return
}
コード例 #9
0
ファイル: txcmds.go プロジェクト: liudch/gocoin
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")
}
コード例 #10
0
ファイル: textui.go プロジェクト: piotrnar/gocoin
func send_inv(par string) {
	cs := strings.Split(par, " ")
	if len(cs) != 2 {
		println("Specify hash and type")
		return
	}
	ha := btc.NewUint256FromString(cs[1])
	if ha == nil {
		println("Incorrect hash")
		return
	}
	v, e := strconv.ParseInt(cs[0], 10, 32)
	if e != nil {
		println("Incorrect type:", e.Error())
		return
	}
	network.NetRouteInv(uint32(v), ha, nil)
	fmt.Println("Inv sent to all peers")
}
コード例 #11
0
ファイル: unspent.go プロジェクト: piotrnar/gocoin
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
}
コード例 #12
0
ファイル: txcmds.go プロジェクト: piotrnar/gocoin
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("")
	}
}
コード例 #13
0
ファイル: textui.go プロジェクト: vancsj/gocoin
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)
}
コード例 #14
0
ファイル: textui.go プロジェクト: piotrnar/gocoin
func dump_block(s string) {
	h := btc.NewUint256FromString(s)
	if h == nil {
		println("Specify block's hash")
		return
	}
	crec, _, er := common.BlockChain.Blocks.BlockGetExt(btc.NewUint256(h.Hash[:]))
	if er != nil {
		println(er.Error())
		return
	}

	ioutil.WriteFile(h.String()+".bin", crec.Data, 0700)
	if crec.Block == nil {
		crec.Block, _ = btc.NewBlock(crec.Data)
	}
	if crec.Block.OldData == nil {
		crec.Block.BuildTxList()
	}
	ioutil.WriteFile(h.String()+".old", crec.Block.OldData, 0700)

	fmt.Println("Block saved")
}
コード例 #15
0
ファイル: tx_test.go プロジェクト: bityuan/gocoin
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)
			}
		}
	}
}
コード例 #16
0
ファイル: init.go プロジェクト: piotrnar/gocoin
func host_init() {
	var e error
	BtcRootDir := sys.BitcoinHome()
	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 += common.DataSubdir() + string(os.PathSeparator)
		BtcRootDir += "testnet3" + string(os.PathSeparator)
		common.MaxPeersNeeded = 2000
	} else {
		common.GenesisBlock = btc.NewUint256FromString("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f")
		common.Magic = [4]byte{0xF9, 0xBE, 0xB4, 0xD9}
		common.GocoinHomeDir += common.DataSubdir() + string(os.PathSeparator)
		common.MaxPeersNeeded = 5000
	}

	// Lock the folder
	os.MkdirAll(common.GocoinHomeDir, 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")
			}
		}
	}

	fmt.Println("Loading UTXO-db and P2SH/P2KH outputs of", btc.UintToBtc(common.AllBalMinVal), "BTC or more")

	__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,
		UTXOVolatileMode:     common.FLAG.VolatileUTXO,
		UndoBlocks:           common.FLAG.UndoBlocks,
		SetBlocksDBCacheSize: true, BlocksDBCacheSize: int(common.CFG.Memory.MaxCachedBlocks)}

	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)
	}
	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

}
コード例 #17
0
ファイル: sendtx.go プロジェクト: liudch/gocoin
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)
}
コード例 #18
0
ファイル: unspent.go プロジェクト: vancsj/gocoin
// 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, AddrVerPubkey()))
					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)
		}
	}
}
コード例 #19
0
ファイル: init.go プロジェクト: vancsj/gocoin
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")
			}
		}
	}

	// 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{NotifyTx: wallet.TxNotify,
		NotifyStealthTx: wallet.StealthNotify,
		LoadWalk:        wallet.NewUTXO, LoadFlush: wallet.DoPendingStealths}

	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
}
コード例 #20
0
ファイル: txs.go プロジェクト: bityuan/gocoin
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 {
		if len(r.Form["ownonly"]) > 0 && v.Own == 0 {
			continue
		}
		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>"))
}
コード例 #21
0
ファイル: txs.go プロジェクト: piotrnar/gocoin
func xml_txs2s(w http.ResponseWriter, r *http.Request) {
	if !ipchecker(r) {
		return
	}

	w.Header()["Content-Type"] = []string{"text/xml"}

	if len(r.Form["minedid"]) > 0 && len(r.Form["minedat"]) > 0 {
		output_utxo_tx_xml(w, r.Form["minedid"][0], r.Form["minedat"][0])
		return
	}

	if len(r.Form["id"]) > 0 {
		txid := btc.NewUint256FromString(r.Form["id"][0])
		if txid == nil {
			return
		}
		network.TxMutex.Lock()
		defer network.TxMutex.Unlock()
		if t2s, ok := network.TransactionsToSend[txid.BIdx()]; ok {
			tx_xml(w, t2s, true)
		} else {
			w.Write([]byte("<tx>"))
			fmt.Fprint(w, "<id>", txid.String(), "</id>")
			w.Write([]byte("<status>Not found</status>"))
			w.Write([]byte("</tx>"))
		}
		return
	}

	if checksid(r) {
		if len(r.Form["del"]) > 0 {
			tid := btc.NewUint256FromString(r.Form["del"][0])
			if tid != nil {
				network.TxMutex.Lock()
				if tts, ok := network.TransactionsToSend[tid.BIdx()]; ok {
					network.DeleteToSend(tts)
				}
				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()
				}
			}
		}

		if len(r.Form["cnt"]) > 0 {
			u, e := strconv.ParseUint(r.Form["cnt"][0], 10, 32)
			if e == nil && u > 0 && u < 10e3 {
				txs2s_count = int(u)
			}
		}

		if len(r.Form["sort"]) > 0 && len(r.Form["sort"][0]) == 3 {
			txs2s_sort = r.Form["sort"][0]
		}

		txs2s_sort_desc = len(r.Form["descending"]) > 0
	}

	network.TxMutex.Lock()
	defer network.TxMutex.Unlock()

	sorted := make(sortedTxList, len(network.TransactionsToSend))
	var cnt int
	for _, v := range network.TransactionsToSend {
		if len(r.Form["ownonly"]) > 0 && v.Own == 0 {
			continue
		}
		sorted[cnt] = v
		cnt++
	}
	sorted = sorted[:cnt]
	sort.Sort(sorted)

	w.Write([]byte("<txpool>"))
	for cnt = 0; cnt < len(sorted) && cnt < txs2s_count; cnt++ {
		v := sorted[cnt]
		tx_xml(w, v, false)
	}
	w.Write([]byte("</txpool>"))
}
コード例 #22
0
ファイル: main.go プロジェクト: vancsj/gocoin
	"github.com/piotrnar/gocoin/lib/btc"
	"github.com/piotrnar/gocoin/lib/chain"
	"github.com/piotrnar/gocoin/lib/others/sys"
	"os"
	"os/signal"
	"runtime"
	"runtime/debug"
	"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   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
)
コード例 #23
0
ファイル: bdb.go プロジェクト: piotrnar/gocoin
func main() {
	flag.BoolVar(&fl_help, "h", false, "Show help")
	flag.UintVar(&fl_block, "block", 0, "Print details of the given block number (or start -verify from it)")
	flag.BoolVar(&fl_scan, "scan", false, "Scan database for first extra blocks")
	flag.BoolVar(&fl_defrag, "defrag", false, "Purge all the orphaned blocks")
	flag.UintVar(&fl_stop, "stop", 0, "Stop after so many scan errors")
	flag.StringVar(&fl_dir, "dir", "", "Use blockdb from this directory")
	flag.StringVar(&fl_split, "split", "", "Split blockdb at this block's hash")
	flag.UintVar(&fl_skip, "skip", 0, "Skip this many blocks when splitting")
	flag.StringVar(&fl_append, "append", "", "Append blocks from this folder to the database")
	flag.BoolVar(&fl_trunc, "trunc", false, "Truncate insted of splitting")
	flag.BoolVar(&fl_commit, "commit", false, "Optimize the size of the data file")
	flag.BoolVar(&fl_verify, "verify", false, "Verify each block inside the database")
	flag.StringVar(&fl_savebl, "savebl", "", "Save block with the given hash to disk")
	flag.BoolVar(&fl_resetflags, "resetflags", false, "Reset all Invalid and Trusted flags when defragmenting")

	flag.Parse()

	if fl_help {
		flag.PrintDefaults()
		return
	}

	if fl_dir != "" && fl_dir[len(fl_dir)-1] != os.PathSeparator {
		fl_dir += string(os.PathSeparator)
	}

	if fl_append != "" {
		if fl_append[len(fl_append)-1] != os.PathSeparator {
			fl_append += string(os.PathSeparator)
		}
		fmt.Println("Loading", fl_append+"blockchain.new")
		dat, er := ioutil.ReadFile(fl_append + "blockchain.new")
		if er != nil {
			fmt.Println(er.Error())
			return
		}

		f, er := os.Open(fl_append + "blockchain.dat")
		if er != nil {
			fmt.Println(er.Error())
			return
		}

		fo, er := os.OpenFile(fl_dir+"blockchain.dat", os.O_WRONLY, 0600)
		if er != nil {
			f.Close()
			fmt.Println(er.Error())
			return
		}
		datfilelen, _ := fo.Seek(0, os.SEEK_END)

		fmt.Println("Appending blocks data to blockchain.dat")
		for {
			var buf [1024 * 1024]byte
			n, _ := f.Read(buf[:])
			if n > 0 {
				fo.Write(buf[:n])
			}
			if n != len(buf) {
				break
			}
		}
		fo.Close()
		f.Close()

		fmt.Println("Now appending", len(dat)/136, "records to blockchain.new")
		fo, er = os.OpenFile(fl_dir+"blockchain.new", os.O_WRONLY, 0600)
		if er != nil {
			f.Close()
			fmt.Println(er.Error())
			return
		}
		fo.Seek(0, os.SEEK_END)

		for off := 0; off < len(dat); off += 136 {
			sl := dat[off : off+136]
			newoffs := binary.LittleEndian.Uint64(sl[40:48]) + uint64(datfilelen)
			binary.LittleEndian.PutUint64(sl[40:48], newoffs)
			fo.Write(sl)
		}
		fo.Close()

		return
	}

	fmt.Println("Loading", fl_dir+"blockchain.new")
	dat, er := ioutil.ReadFile(fl_dir + "blockchain.new")
	if er != nil {
		fmt.Println(er.Error())
		return
	}

	fmt.Println(len(dat)/136, "records")

	if fl_scan {
		var scan_errs uint
		last_bl_height := binary.LittleEndian.Uint32(dat[36:40])
		exp_offset := uint64(binary.LittleEndian.Uint32(dat[48:52]))
		fmt.Println("Scanning database for first extra block(s)...")
		fmt.Println("First block in the file has height", last_bl_height)
		for off := 136; off < len(dat); off += 136 {
			sl := dat[off : off+136]
			height := binary.LittleEndian.Uint32(sl[36:40])
			off_in_bl := binary.LittleEndian.Uint64(sl[40:48])

			if height != last_bl_height+1 {
				fmt.Println("Out of sequence block number", height, last_bl_height+1, "found at offset", off)
				print_record(dat[off-136 : off])
				print_record(dat[off : off+136])
				fmt.Println()
				scan_errs++
			}
			if off_in_bl != exp_offset {
				fmt.Println("Spare data found just before block number", height, off_in_bl, exp_offset)
				print_record(dat[off-136 : off])
				print_record(dat[off : off+136])
				scan_errs++
			}

			if fl_stop != 0 && scan_errs >= fl_stop {
				break
			}

			last_bl_height = height

			exp_offset += uint64(binary.LittleEndian.Uint32(sl[48:52]))
		}
		return
	}

	if fl_defrag {
		blks := make(map[[32]byte]*one_tree_node, len(dat)/136)
		for off := 0; off < len(dat); off += 136 {
			sl := new_sl(dat[off : off+136])
			blks[sl.HIdx()] = &one_tree_node{off: off, one_idx_rec: sl}
		}
		var maxbl uint32
		var maxblptr *one_tree_node
		for _, v := range blks {
			v.parent = blks[v.PIdx()]
			h := v.Height()
			if h > maxbl {
				maxbl = h
				maxblptr = v
			} else if h == maxbl {
				maxblptr = nil
			}
		}
		fmt.Println("Max block height =", maxbl)
		if maxblptr == nil {
			fmt.Println("More than one block at maximum height - cannot continue")
			return
		}
		used := make(map[[32]byte]bool)
		var first_block *one_tree_node
		var total_data_size uint64
		for n := maxblptr; n != nil; n = n.parent {
			if n.parent != nil {
				n.parent.next = n
			}
			used[n.PIdx()] = true
			if first_block == nil || first_block.Height() > n.Height() {
				first_block = n
			}
			total_data_size += uint64(n.DLen())
		}
		if len(used) < len(blks) || fl_resetflags {
			fmt.Println("Purge", len(blks)-len(used), "blocks from the index file...")
			f, e := os.Create(fl_dir + "blockchain.tmp")
			if e != nil {
				println(e.Error())
				return
			}
			var off int
			for n := first_block; n != nil; n = n.next {
				n.off = off
				n.sl[0] = n.sl[0] & 0xfc
				f.Write(n.sl)
				off += len(n.sl)
			}
			f.Close()
			os.Rename(fl_dir+"blockchain.tmp", fl_dir+"blockchain.new")
		} else {
			fmt.Println("The index file looks perfect")
		}

		for n := first_block; n != nil && n.next != nil; n = n.next {
			if n.next.DPos() < n.DPos() {
				fmt.Println("There is a problem... swapped order in the data file!", n.off)
				return
			}
		}

		fdat, er := os.OpenFile(fl_dir+"blockchain.dat", os.O_RDWR, 0600)
		if er != nil {
			println(er.Error())
			return
		}

		if fl, _ := fdat.Seek(0, os.SEEK_END); uint64(fl) == total_data_size {
			fdat.Close()
			fmt.Println("All good - blockchain.dat has an optimal length")
			return
		}

		if !fl_commit {
			fdat.Close()
			fmt.Println("Warning: blockchain.dat shall be defragmented. Use \"-defrag -commit\"")
			return
		}

		fidx, er := os.OpenFile(fl_dir+"blockchain.new", os.O_RDWR, 0600)
		if er != nil {
			println(er.Error())
			return
		}

		// Capture Ctrl+C
		killchan := make(chan os.Signal, 1)
		signal.Notify(killchan, os.Interrupt, os.Kill)

		var doff uint64
		var prv_perc uint64 = 101
		buf := make([]byte, 0x100000)
		for n := first_block; n != nil; n = n.next {
			perc := 1000 * doff / total_data_size
			dp := n.DPos()
			dl := n.DLen()
			if perc != prv_perc {
				fmt.Printf("\rDefragmenting data file - %.1f%% (%d bytes saved so far)...",
					float64(perc)/10.0, dp-doff)
				prv_perc = perc
			}
			if dp > doff {
				if len(buf) < int(dl) {
					println("WARNIGN: grow block buffer to ")
					buf = make([]byte, dl)
				}
				fdat.Seek(int64(dp), os.SEEK_SET)
				fdat.Read(buf[:int(dl)])

				n.SetDPos(doff)

				fdat.Seek(int64(doff), os.SEEK_SET)
				fdat.Write(buf[:int(dl)])

				fidx.Seek(int64(n.off), os.SEEK_SET)
				fidx.Write(n.sl)
			}
			doff += uint64(dl)

			select {
			case <-killchan:
				fmt.Println("interrupted")
				fidx.Close()
				fdat.Close()
				fmt.Println("Database closed - should be still usable, but no space saved")
				return
			default:
			}
		}

		fidx.Close()
		fdat.Close()
		fmt.Println()

		fmt.Println("Truncating blockchain.dat at position", doff)
		os.Truncate(fl_dir+"blockchain.dat", int64(doff))

		return
	}

	if fl_verify {
		fdat, er := os.OpenFile(fl_dir+"blockchain.dat", os.O_RDWR, 0600)
		if er != nil {
			println(er.Error())
			return
		}

		dat_file_size, _ := fdat.Seek(0, os.SEEK_END)

		buf := make([]byte, 0x100000)
		var prv_perc int64 = -1
		var totlen uint64
		var done sync.WaitGroup
		for off := 0; off < len(dat); off += 136 {
			sl := new_sl(dat[off : off+136])

			dp := int64(sl.DPos())
			le := int(sl.DLen())
			hei := uint(sl.Height())

			perc := 1000 * dp / dat_file_size
			if perc != prv_perc {
				fmt.Printf("\rVerifying blocks data - %.1f%% @ %d / %dMB processed...",
					float64(perc)/10.0, hei, totlen>>20)
				prv_perc = perc
			}

			if fl_block != 0 && hei < fl_block {
				continue
			}

			fdat.Seek(dp, os.SEEK_SET)
			fdat.Read(buf[:le])

			blk := decomp_block(sl.Flags(), buf[:le])

			done.Add(1)
			go func(blk []byte, sl one_idx_rec, off int) {
				verify_block(blk, sl, off)
				done.Done()
			}(blk, sl, off)

			totlen += uint64(len(blk))
		}
		done.Wait() // wait for all the goroutines to complete
		return
	}

	if fl_block != 0 {
		for off := 0; off < len(dat); off += 136 {
			sl := dat[off : off+136]
			height := binary.LittleEndian.Uint32(sl[36:40])
			if uint(height) == fl_block {
				print_record(dat[off : off+136])
			}
		}
		return
	}

	if fl_split != "" {
		th := btc.NewUint256FromString(fl_split)
		if th == nil {
			println("incorrect block hash")
			return
		}
		for off := 0; off < len(dat); off += 136 {
			sl := dat[off : off+136]
			height := binary.LittleEndian.Uint32(sl[36:40])
			bh := btc.NewSha2Hash(sl[56:136])
			if bh.Hash == th.Hash {
				trunc_idx_offs := int64(off)
				trunc_dat_offs := int64(binary.LittleEndian.Uint64(sl[40:48]))
				fmt.Println("Truncate blockchain.new at offset", trunc_idx_offs)
				fmt.Println("Truncate blockchain.dat at offset", trunc_dat_offs)
				if !fl_trunc {
					new_dir := fl_dir + fmt.Sprint(height) + string(os.PathSeparator)
					os.Mkdir(new_dir, os.ModePerm)

					f, e := os.Open(fl_dir + "blockchain.dat")
					if e != nil {
						fmt.Println(e.Error())
						return
					}
					df, e := os.Create(new_dir + "blockchain.dat")
					if e != nil {
						f.Close()
						fmt.Println(e.Error())
						return
					}

					f.Seek(trunc_dat_offs, os.SEEK_SET)

					fmt.Println("But fist save the rest in", new_dir, "...")
					if fl_skip != 0 {
						fmt.Println("Skip", fl_skip, "blocks in the output file")
						for fl_skip > 0 {
							skipbytes := binary.LittleEndian.Uint32(sl[48:52])
							fmt.Println(" -", skipbytes, "bytes of block", binary.LittleEndian.Uint32(sl[36:40]))
							off += 136
							if off < len(dat) {
								sl = dat[off : off+136]
								fl_skip--
							} else {
								break
							}
						}
					}

					for {
						var buf [1024 * 1024]byte
						n, _ := f.Read(buf[:])
						if n > 0 {
							df.Write(buf[:n])
						}
						if n != len(buf) {
							break
						}
					}
					df.Close()
					f.Close()

					df, e = os.Create(new_dir + "blockchain.new")
					if e != nil {
						f.Close()
						fmt.Println(e.Error())
						return
					}
					var off2 int
					for off2 = off; off2 < len(dat); off2 += 136 {
						sl := dat[off2 : off2+136]
						newoffs := binary.LittleEndian.Uint64(sl[40:48]) - uint64(trunc_dat_offs)
						binary.LittleEndian.PutUint64(sl[40:48], newoffs)
						df.Write(sl)
					}
					df.Close()
				}

				os.Truncate(fl_dir+"blockchain.new", trunc_idx_offs)
				os.Truncate(fl_dir+"blockchain.dat", trunc_dat_offs)
				return
			}
		}
		fmt.Println("Block not found - nothing truncated")
	}

	if fl_savebl != "" {
		bh := btc.NewUint256FromString(fl_savebl)
		if bh == nil {
			println("Incortrect block hash:", fl_savebl)
			return
		}
		for off := 0; off < len(dat); off += 136 {
			sl := new_sl(dat[off : off+136])
			if bytes.Equal(sl.Hash(), bh.Hash[:]) {
				f, er := os.Open(fl_dir + "blockchain.dat")
				if er != nil {
					println(er.Error())
					return
				}
				buf := make([]byte, int(sl.DLen()))
				f.Seek(int64(sl.DPos()), os.SEEK_SET)
				f.Read(buf)
				f.Close()
				ioutil.WriteFile(bh.String()+".bin", decomp_block(sl.Flags(), buf), 0600)
				fmt.Println(bh.String()+".bin written to disk. It has height", sl.Height())
				return
			}
		}
		fmt.Println("Block", bh.String(), "not found in the database")
		return
	}

	var minbh, maxbh uint32
	minbh = binary.LittleEndian.Uint32(dat[36:40])
	maxbh = minbh
	for off := 136; off < len(dat); off += 136 {
		sl := new_sl(dat[off : off+136])
		bh := sl.Height()
		if bh > maxbh {
			maxbh = bh
		} else if bh < minbh {
			minbh = bh
		}
	}
	fmt.Println("Block heights from", minbh, "to", maxbh)
}
コード例 #24
0
ファイル: sendtx.go プロジェクト: piotrnar/gocoin
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

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

		seq, er := strconv.ParseInt(r.Form["tx_seq"][0], 10, 64)
		if er != nil || seq < -2 || seq > 0xffffffff {
			err = "Incorrect Sequence value: " + r.Form["tx_seq"][0]
			goto error
		}

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

		lck := new(usif.OneLock)
		lck.In.Add(1)
		lck.Out.Add(1)
		usif.LocksChan <- lck
		lck.In.Wait()
		defer lck.Out.Done()

		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)}
						if res, er := common.BlockChain.Unspent.UnspentGet(&po); er == nil {
							addr := btc.NewAddrFromPkScript(res.Pk_script, common.Testnet)

							unsp := &chain.OneUnspentTx{TxPrevOut: po, Value: res.Value,
								MinedAt: res.BlockHeight, Coinbase: res.WasCoinbase, BtcAddr: addr}

							thisbal = append(thisbal, unsp)

							// Add the input to our tx
							tin := new(btc.TxIn)
							tin.Input = po
							tin.Sequence = uint32(seq)
							tx.TxIn = append(tx.TxIn, tin)

							// Add the value to total input value
							totalinput += res.Value

							// If no change specified, use the first input addr as it
							if change_addr == nil {
								change_addr = addr
							}
						}
					}
				}
			}
		}

		if change_addr == nil {
			// There werte no inputs
			return
		}
		//wallet.BalanceMutex.Lock()
		//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
		}

		pay_cmd += fmt.Sprint(" -seq ", seq)

		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")
			if dat, er := common.BlockChain.GetRawTx(thisbal[i].MinedAt, txid); er == nil {
				fz.Write(dat)
			} else {
				println(er.Error())
			}
		}

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

		if pay_cmd != "" {
			fz, _ = zi.Create(common.CFG.WebUI.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)
}
コード例 #25
0
ファイル: main.go プロジェクト: liudch/gocoin
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
}
コード例 #26
0
ファイル: importblocks.go プロジェクト: liudch/gocoin
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)
}
コード例 #27
0
ファイル: main.go プロジェクト: vancsj/gocoin
func main() {
	fmt.Println("Gocoin blockchain downloader version", lib.Version)
	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)

	sys.LockDatabaseDir(GocoinHomeDir)
	defer sys.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
}
コード例 #28
0
ファイル: fetchtx.go プロジェクト: liudch/gocoin
// 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
}