Beispiel #1
0
// apply the chnages to the balance folder
func apply_to_balance(tx *btc.Tx) {
	f, _ := os.Create("balance/unspent.txt")
	if f != nil {
		// append new outputs at the end of unspentOuts
		ioutil.WriteFile("balance/"+tx.Hash.String()+".tx", tx.Serialize(), 0600)

		fmt.Println("Adding", len(tx.TxOut), "new output(s) to the balance/ folder...")
		for out := range tx.TxOut {
			if k := pkscr_to_key(tx.TxOut[out].Pk_script); k != nil {
				uns := new(unspRec)
				uns.key = k
				uns.TxPrevOut.Hash = tx.Hash.Hash
				uns.TxPrevOut.Vout = uint32(out)
				uns.label = fmt.Sprint("# ", btc.UintToBtc(tx.TxOut[out].Value), " BTC @ ", k.BtcAddr.String())
				//stealth bool TODO: maybe we can fix it...
				unspentOuts = append(unspentOuts, uns)
			}
		}

		for j := range unspentOuts {
			if !unspentOuts[j].spent {
				fmt.Fprintln(f, unspentOuts[j].String())
			}
		}
		f.Close()
	} else {
		println("ERROR: Cannot create balance/unspent.txt")
	}
}
Beispiel #2
0
func (db *UnspentDB) PrintCoinAge() {
	const chunk = 10000
	var maxbl uint32
	type onerec struct {
		cnt, bts, val, valcb uint64
	}
	age := make(map[uint32]*onerec)
	for i := range db.tdb {
		db.DbN(i).BrowseAll(func(k qdb.KeyType, v []byte) uint32 {
			rec := NewQdbRecStatic(k, v)
			a := rec.InBlock
			if a > maxbl {
				maxbl = a
			}
			a /= chunk
			tmp := age[a]
			if tmp == nil {
				tmp = new(onerec)
			}
			for _, ou := range rec.Outs {
				if ou != nil {
					tmp.val += ou.Value
					if rec.Coinbase {
						tmp.valcb += ou.Value
					}
					tmp.cnt++
				}
			}
			tmp.bts += uint64(len(v))
			age[a] = tmp
			return 0
		})
	}
	for i := uint32(0); i <= (maxbl / chunk); i++ {
		tb := (i+1)*chunk - 1
		if tb > maxbl {
			tb = maxbl
		}
		cnt := uint64(tb-i*chunk) + 1
		fmt.Printf(" Blocks  %6d ... %6d: %9d records, %5d MB, %18s/%16s BTC.  Per block:%7.1f records,%8d,%15s BTC\n",
			i*chunk, tb, age[i].cnt, age[i].bts>>20, btc.UintToBtc(age[i].val), btc.UintToBtc(age[i].valcb),
			float64(age[i].cnt)/float64(cnt), (age[i].bts / cnt), btc.UintToBtc(age[i].val/cnt))
	}
}
Beispiel #3
0
func (db *UnspentDB) PrintCoinAge() {
	const chunk = 10000
	var maxbl uint32
	type rec struct {
		cnt, bts, val uint64
	}
	age := make(map[uint32]*rec)
	for i := range db.unspent.tdb {
		db.unspent.dbN(i).BrowseAll(func(k qdb.KeyType, v []byte) uint32 {
			a := binary.LittleEndian.Uint32(v[44:48])
			if a > maxbl {
				maxbl = a
			}
			a /= chunk
			tmp := age[a]
			if tmp == nil {
				tmp = new(rec)
			}
			tmp.val += binary.LittleEndian.Uint64(v[36:44])
			tmp.cnt++
			tmp.bts += uint64(len(v))
			age[a] = tmp
			return 0
		})
	}
	for i := uint32(0); i <= (maxbl / chunk); i++ {
		tb := (i+1)*chunk - 1
		if tb > maxbl {
			tb = maxbl
		}
		cnt := uint64(tb-i*chunk) + 1
		fmt.Printf(" Blocks  %6d ... %6d: %9d records, %5d MB, %18s BTC.  Per block:%7.1f records,%8d,%15s BTC\n",
			i*chunk, tb, age[i].cnt, age[i].bts>>20, btc.UintToBtc(age[i].val),
			float64(age[i].cnt)/float64(cnt), (age[i].bts / cnt), btc.UintToBtc(age[i].val/cnt))
	}
}
Beispiel #4
0
func show_balance_stats(p string) {
	println("CachedAddrs count:", len(wallet.CachedAddrs))
	println("CacheUnspentIdx count:", len(wallet.CacheUnspentIdx))
	println("CacheUnspent count:", len(wallet.CacheUnspent))
	println("StealthAddrs count:", len(wallet.StealthAdCache))
	println("StealthSecrets:", len(wallet.StealthSecrets))
	if p != "" {
		wallet.BalanceMutex.Lock()
		for i := range wallet.CacheUnspent {
			if len(wallet.CacheUnspent[i].AllUnspentTx) == 0 {
				fmt.Printf("%5d) %s: empty\n", i, wallet.CacheUnspent[i].BtcAddr.String())
			} else {
				var val uint64
				for j := range wallet.CacheUnspent[i].AllUnspentTx {
					val += wallet.CacheUnspent[i].AllUnspentTx[j].Value
				}
				fmt.Printf("%5d) %s: %s BTC in %d\n", i, wallet.CacheUnspent[i].BtcAddr.String(),
					btc.UintToBtc(val), len(wallet.CacheUnspent[i].AllUnspentTx))
			}
		}
		wallet.BalanceMutex.Unlock()
	}
}
Beispiel #5
0
func list_unspent(addr string) {
	fmt.Println("Checking unspent coins for addr", addr)

	ad, e := btc.NewAddrFromString(addr)
	if e != nil {
		println(e.Error())
		return
	}

	unsp := wallet.GetAllUnspent(ad)
	if len(unsp) == 0 {
		fmt.Println(ad.String(), "has no coins")
	} else {
		var tot uint64
		sort.Sort(unsp)
		for i := range unsp {
			tot += unsp[i].Value
		}
		fmt.Println(ad.String(), "has", btc.UintToBtc(tot), "BTC in", len(unsp), "records:")
		for i := range unsp {
			fmt.Println(unsp[i].String())
		}
	}
}
Beispiel #6
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

		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)
}
Beispiel #7
0
func p_miners(w http.ResponseWriter, r *http.Request) {
	if !ipchecker(r) {
		return
	}

	common.ReloadMiners()

	m := make(map[string]omv, 20)
	var om omv
	cnt := 0
	common.Last.Mutex.Lock()
	end := common.Last.Block
	common.Last.Mutex.Unlock()
	var lastts int64
	var diff float64
	var totbts uint64
	var totfees uint64
	current_mid := -1
	now := time.Now().Unix()

	common.LockCfg()
	minerid := common.CFG.Beeps.MinerID
	common.UnlockCfg()

	next_diff_change := 2016 - end.Height%2016

	block_versions := make(map[uint32]uint)

	// bip100
	bip100_voting := make(map[string]uint)
	//var bip100, bip100v uint64
	bip100x := regexp.MustCompile("/BV{0,1}[0-9]+[M]{0,1}/")
	//bip100rx := regexp.MustCompile("/B[0-9]+[M]{0,1}/")

	for ; end != nil; cnt++ {
		if now-int64(end.Timestamp()) > int64(common.CFG.MiningStatHours)*3600 {
			break
		}
		lastts = int64(end.Timestamp())
		bl, _, e := common.BlockChain.Blocks.BlockGet(end.BlockHash)
		if e != nil {
			return
		}

		block, e := btc.NewBlock(bl)
		cbasetx, _ := btc.NewTx(bl[block.TxOffset:])

		block_versions[binary.LittleEndian.Uint32(bl[0:4])]++
		diff += btc.GetDifficulty(end.Bits())
		miner, mid := common.TxMiner(cbasetx)
		if mid == -1 {
			miner = "<i>" + miner + "</i>"
		}
		om = m[miner]
		om.cnt++
		om.bts += uint64(len(bl))
		om.mid = mid

		// Blocks reward
		var rew uint64
		for o := range cbasetx.TxOut {
			rew += cbasetx.TxOut[o].Value
		}
		om.fees += rew - btc.GetBlockReward(end.Height)

		// bip-100
		res := bip100x.Find(cbasetx.TxIn[0].ScriptSig)
		if res != nil {
			bip100_voting[string(res)]++
		}

		m[miner] = om
		if mid != -1 && current_mid == -1 && minerid == string(common.MinerIds[mid].Tag) {
			current_mid = mid
		}
		totbts += uint64(len(bl))
		end = end.Parent
	}

	if cnt == 0 {
		write_html_head(w, r)
		w.Write([]byte(fmt.Sprint("No blocks in last ", common.CFG.MiningStatHours, " hours")))
		write_html_tail(w)
		return
	}

	srt := make(onemiernstat, len(m))
	i := 0
	for k, v := range m {
		srt[i].name = k
		srt[i].omv = v
		i++
	}
	sort.Sort(srt)

	mnrs := load_template("miners.html")
	onerow := load_template("miners_row.html")

	diff /= float64(cnt)
	bph := float64(cnt) / float64(common.CFG.MiningStatHours)
	hrate := bph / 6 * diff * 7158278.826667
	mnrs = strings.Replace(mnrs, "{MINING_HOURS}", fmt.Sprint(common.CFG.MiningStatHours), 1)
	mnrs = strings.Replace(mnrs, "{BLOCKS_COUNT}", fmt.Sprint(cnt), 1)
	mnrs = strings.Replace(mnrs, "{FIRST_BLOCK_TIME}", time.Unix(lastts, 0).Format("2006-01-02 15:04:05"), 1)
	mnrs = strings.Replace(mnrs, "{AVG_BLOCKS_PER_HOUR}", fmt.Sprintf("%.2f", bph), 1)
	mnrs = strings.Replace(mnrs, "{AVG_DIFFICULTY}", common.NumberToString(diff), 1)
	mnrs = strings.Replace(mnrs, "{AVG_HASHDATE}", common.HashrateToString(hrate), 1)
	mnrs = strings.Replace(mnrs, "{AVG_BLOCKSIZE}", fmt.Sprintf("%.1fKB", float64(totbts)/float64(cnt)/1000), 1)
	mnrs = strings.Replace(mnrs, "{DIFF_CHANGE_IN}", fmt.Sprint(next_diff_change), 1)
	mnrs = strings.Replace(mnrs, "{MINER_MON_IDX}", fmt.Sprint(current_mid), 1)

	for i := range srt {
		s := onerow
		s = strings.Replace(s, "{MINER_NAME}", srt[i].name, 1)
		s = strings.Replace(s, "{BLOCK_COUNT}", fmt.Sprint(srt[i].cnt), 1)
		s = strings.Replace(s, "{TOTAL_PERCENT}", fmt.Sprintf("%.0f", 100*float64(srt[i].cnt)/float64(cnt)), 1)
		s = strings.Replace(s, "{MINER_HASHRATE}", common.HashrateToString(hrate*float64(srt[i].cnt)/float64(cnt)), 1)
		s = strings.Replace(s, "{AVG_BLOCK_SIZE}", fmt.Sprintf("%.1fKB", float64(srt[i].bts)/float64(srt[i].cnt)/1000), 1)
		s = strings.Replace(s, "{MINER_ID}", fmt.Sprint(srt[i].mid), -1)
		s = strings.Replace(s, "<!--TOTAL_FEES-->", btc.UintToBtc(srt[i].fees), -1)
		s = strings.Replace(s, "<!--FEE_PER_BYTE-->", fmt.Sprint(srt[i].fees/srt[i].bts), -1)
		mnrs = templ_add(mnrs, "<!--MINER_ROW-->", s)
		totfees += srt[i].fees
	}

	mnrs = strings.Replace(mnrs, "<!--TOTAL_MINING_FEES-->", btc.UintToBtc(totfees), 1)
	mnrs = strings.Replace(mnrs, "<!--AVERAGE_FEE_PER_BYTE-->", fmt.Sprint(totfees/totbts), 1)

	var bv string
	for k, v := range block_versions {
		if bv != "" {
			bv += ",&nbsp;&nbsp;"
		}
		bv += fmt.Sprintf("%d (%d%%) x <b>v%d</b>", v, 100*int(v)/cnt, k)
	}
	mnrs = strings.Replace(mnrs, "<!--BLOCK_VERSIONS-->", bv, 1)

	// bip100
	bv = ""
	for k, v := range bip100_voting {
		if bv != "" {
			bv += " + "
		}
		bv += fmt.Sprintf("%sx%d", k, v)
	}

	mnrs = strings.Replace(mnrs, "<!--BLOCKSIZE_VOTES-->", bv, 1)

	write_html_head(w, r)
	w.Write([]byte(mnrs))
	write_html_tail(w)
}
Beispiel #8
0
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

}
Beispiel #9
0
// prepare a signed transaction
func make_signed_tx() {
	// Make an empty transaction
	tx := new(btc.Tx)
	tx.Version = 1
	tx.Lock_time = 0

	// Select as many inputs as we need to pay the full amount (with the fee)
	var btcsofar uint64
	for i := range unspentOuts {
		if unspentOuts[i].key == nil {
			continue
		}
		uo := getUO(&unspentOuts[i].TxPrevOut)
		// add the input to our transaction:
		tin := new(btc.TxIn)
		tin.Input = unspentOuts[i].TxPrevOut
		tin.Sequence = 0xffffffff
		tx.TxIn = append(tx.TxIn, tin)

		btcsofar += uo.Value
		unspentOuts[i].spent = true
		if !*useallinputs && (btcsofar >= spendBtc+feeBtc) {
			break
		}
	}
	if btcsofar < (spendBtc + feeBtc) {
		fmt.Println("ERROR: You have", btc.UintToBtc(btcsofar), "BTC, but you need",
			btc.UintToBtc(spendBtc+feeBtc), "BTC for the transaction")
		cleanExit(1)
	}
	changeBtc = btcsofar - (spendBtc + feeBtc)
	if *verbose {
		fmt.Printf("Spending %d out of %d outputs...\n", len(tx.TxIn), len(unspentOuts))
	}

	// Build transaction outputs:
	for o := range sendTo {
		outs, er := btc.NewSpendOutputs(sendTo[o].addr, sendTo[o].amount, testnet)
		if er != nil {
			fmt.Println("ERROR:", er.Error())
			cleanExit(1)
		}
		tx.TxOut = append(tx.TxOut, outs...)
	}

	if changeBtc > 0 {
		// Add one more output (with the change)
		chad := get_change_addr()
		if *verbose {
			fmt.Println("Sending change", changeBtc, "to", chad.String())
		}
		outs, er := btc.NewSpendOutputs(chad, changeBtc, testnet)
		if er != nil {
			fmt.Println("ERROR:", er.Error())
			cleanExit(1)
		}
		tx.TxOut = append(tx.TxOut, outs...)
	}

	if *message != "" {
		// Add NULL output with an arbitrary message
		scr := new(bytes.Buffer)
		scr.WriteByte(0x6a) // OP_RETURN
		btc.WritePutLen(scr, uint32(len(*message)))
		scr.Write([]byte(*message))
		tx.TxOut = append(tx.TxOut, &btc.TxOut{Value: 0, Pk_script: scr.Bytes()})
	}

	signed := sign_tx(tx)
	write_tx_file(tx)

	if apply2bal && signed {
		apply_to_balance(tx)
	}
}
Beispiel #10
0
// dump raw transaction
func dump_raw_tx() {
	tx := raw_tx_from_file(*dumptxfn)
	if tx == nil {
		fmt.Println("ERROR: Cannot decode the raw transaction")
		return
	}

	var unsigned int

	fmt.Println("ID:", tx.Hash.String())
	fmt.Println("Tx Version:", tx.Version)
	if tx.IsCoinBase() {
		if len(tx.TxIn[0].ScriptSig) >= 4 && tx.TxIn[0].ScriptSig[0] == 3 {
			fmt.Println("Coinbase TX from block height", uint(tx.TxIn[0].ScriptSig[1])|
				uint(tx.TxIn[0].ScriptSig[2])<<8|uint(tx.TxIn[0].ScriptSig[3])<<16)
		} else {
			fmt.Println("Coinbase TX from an unknown block")
		}
		s := hex.EncodeToString(tx.TxIn[0].ScriptSig)
		for len(s) > 0 {
			i := len(s)
			if i > 64 {
				i = 64
			}
			fmt.Println("  ", s[:i])
			s = s[i:]
		}
		//fmt.Println()
	} else {
		fmt.Println("TX IN cnt:", len(tx.TxIn))
		for i := range tx.TxIn {
			fmt.Printf("%4d) %s sl=%d seq=%08x\n", i, tx.TxIn[i].Input.String(),
				len(tx.TxIn[i].ScriptSig), tx.TxIn[i].Sequence)

			if len(tx.TxIn[i].ScriptSig) > 0 {
				if !dump_sigscript(tx.TxIn[i].ScriptSig) {
					unsigned++
				}
			} else {
				unsigned++
			}
		}
	}
	fmt.Println("TX OUT cnt:", len(tx.TxOut))
	for i := range tx.TxOut {
		fmt.Printf("%4d) %20s BTC ", i, btc.UintToBtc(tx.TxOut[i].Value))
		var addr *btc.BtcAddr
		if litecoin {
			addr = ltc.NewAddrFromPkScript(tx.TxOut[i].Pk_script, testnet)
		} else {
			addr = btc.NewAddrFromPkScript(tx.TxOut[i].Pk_script, testnet)
		}
		if addr != nil {
			if addr.Version == AddrVerScript() {
				fmt.Println("to scriptH", addr.String())
			} else {
				fmt.Println("to address", addr.String())
			}
		} else if len(tx.TxOut[i].Pk_script) == 40 && tx.TxOut[i].Pk_script[0] == 0x6a &&
			tx.TxOut[i].Pk_script[1] == 0x26 && tx.TxOut[i].Pk_script[2] == 0x06 {
			fmt.Println("Stealth", hex.EncodeToString(tx.TxOut[i].Pk_script[3:7]),
				hex.EncodeToString(tx.TxOut[i].Pk_script[7:]))
		} else {
			if tx.TxOut[i].Value > 0 {
				fmt.Println("WARNING!!! These coins go to non-standard Pk_script:")
			} else {
				fmt.Println("NULL output to Pk_script:")
			}
			ss, er := btc.ScriptToText(tx.TxOut[i].Pk_script)
			if er == nil {
				for i := range ss {
					fmt.Println("       ", ss[i])
				}
			} else {
				fmt.Println(hex.EncodeToString(tx.TxOut[i].Pk_script))
				fmt.Println(er.Error())
			}
		}
	}
	fmt.Println("Lock Time:", tx.Lock_time)

	if !tx.IsCoinBase() {
		if unsigned > 0 {
			fmt.Println("WARNING:", unsigned, "out of", len(tx.TxIn), "inputs are not signed or signed only patially")
		} else {
			fmt.Println("All", len(tx.TxIn), "transaction inputs seem to be signed")
		}
	}
}
Beispiel #11
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)
}
Beispiel #12
0
// dump raw transaction
func dump_raw_tx() {
	tx := raw_tx_from_file(*dumptxfn)
	if tx == nil {
		fmt.Println("ERROR: Cannot decode the raw transaction")
		return
	}

	var unsigned, totin, totout, noins uint64

	fmt.Println("ID:", tx.Hash.String())
	fmt.Println("Tx Version:", tx.Version)
	if tx.SegWit != nil {
		fmt.Println("Segregated Witness transaction", len(tx.SegWit))
	} else {
		fmt.Println("Regular (non-SegWit) transaction", len(tx.SegWit))
	}
	if tx.IsCoinBase() {
		if len(tx.TxIn[0].ScriptSig) >= 4 && tx.TxIn[0].ScriptSig[0] == 3 {
			fmt.Println("Coinbase TX from block height", uint(tx.TxIn[0].ScriptSig[1])|
				uint(tx.TxIn[0].ScriptSig[2])<<8|uint(tx.TxIn[0].ScriptSig[3])<<16)
		} else {
			fmt.Println("Coinbase TX from an unknown block")
		}
		s := hex.EncodeToString(tx.TxIn[0].ScriptSig)
		for len(s) > 0 {
			i := len(s)
			if i > 64 {
				i = 64
			}
			fmt.Println("  ", s[:i])
			s = s[i:]
		}
		for wia := range tx.SegWit {
			for wib, ww := range tx.SegWit[wia] {
				fmt.Println("  Witness", wia, wib, hex.EncodeToString(ww))
			}
		}
		//fmt.Println()
	} else {
		fmt.Println("TX IN cnt:", len(tx.TxIn))
		for i := range tx.TxIn {
			fmt.Printf("%4d) %s sl=%d seq=%08x\n", i, tx.TxIn[i].Input.String(),
				len(tx.TxIn[i].ScriptSig), tx.TxIn[i].Sequence)

			if intx := tx_from_balance(btc.NewUint256(tx.TxIn[i].Input.Hash[:]), false); intx != nil {
				val := intx.TxOut[tx.TxIn[i].Input.Vout].Value
				totin += val
				fmt.Printf("%15s BTC\n", btc.UintToBtc(val))
			} else {
				noins++
			}

			if len(tx.TxIn[i].ScriptSig) > 0 {
				if !dump_sigscript(tx.TxIn[i].ScriptSig) {
					unsigned++
				}
			} else {
				unsigned++
			}

			if tx.SegWit != nil {
				fmt.Println("      Witness data:")
				for _, ww := range tx.SegWit[i] {
					fmt.Println("       ", hex.EncodeToString(ww))
				}
			}
		}
	}
	fmt.Println("TX OUT cnt:", len(tx.TxOut))
	for i := range tx.TxOut {
		totout += tx.TxOut[i].Value
		fmt.Printf("%4d) %20s BTC ", i, btc.UintToBtc(tx.TxOut[i].Value))
		addr := addr_from_pkscr(tx.TxOut[i].Pk_script)
		if addr != nil {
			if addr.Version == ver_script() {
				fmt.Println("to scriptH", addr.String())
			} else {
				fmt.Println("to address", addr.String())
			}
		} else if len(tx.TxOut[i].Pk_script) == 40 && tx.TxOut[i].Pk_script[0] == 0x6a &&
			tx.TxOut[i].Pk_script[1] == 0x26 && tx.TxOut[i].Pk_script[2] == 0x06 {

			sha := sha256.New()
			sha.Write(tx.TxOut[i].Pk_script[3:40])

			fmt.Println("Stealth", hex.EncodeToString(sha.Sum(nil)[:4]),
				hex.EncodeToString(tx.TxOut[i].Pk_script[7:]))
		} else {
			if tx.TxOut[i].Value > 0 {
				fmt.Println("WARNING!!! These coins go to non-standard Pk_script:")
			} else {
				fmt.Println("NULL output to Pk_script:")
			}
			ss, er := btc.ScriptToText(tx.TxOut[i].Pk_script)
			if er == nil {
				for i := range ss {
					fmt.Println("       ", ss[i])
				}
			} else {
				fmt.Println(hex.EncodeToString(tx.TxOut[i].Pk_script))
				fmt.Println(er.Error())
			}
		}
	}
	fmt.Println("Lock Time:", tx.Lock_time)

	fmt.Println("Output volume:", btc.UintToBtc(totout), "BTC")
	if noins == 0 {
		fmt.Println("Input volume :", btc.UintToBtc(totin), "BTC")
		fmt.Println("Transact. fee:", btc.UintToBtc(totin-totout), "BTC")
	} else {
		fmt.Println("WARNING: Unable to figure out what the fee is")
	}

	if !tx.IsCoinBase() {
		if unsigned > 0 {
			fmt.Println("WARNING:", unsigned, "out of", len(tx.TxIn), "inputs are not signed or signed only patially")
		} else {
			fmt.Println("All", len(tx.TxIn), "transaction inputs seem to be signed")
		}
	}
}
Beispiel #13
0
func all_addrs(par string) {
	var ptkh_outs, ptkh_vals, ptsh_outs, ptsh_vals uint64
	var best SortedWalletAddrs
	var cnt int = 15

	if par != "" {
		if c, e := strconv.ParseUint(par, 10, 32); e == nil {
			cnt = int(c)
		}
	}

	wallet.BalanceMutex.Lock()
	defer wallet.BalanceMutex.Unlock()

	for k, rec := range wallet.AllBalancesP2SH {
		ptsh_vals += rec.Value
		ptsh_outs += uint64(len(rec.Unsp))
		if sort_by_cnt && len(rec.Unsp) >= 1000 || !sort_by_cnt && rec.Value >= 1000e8 {
			best = append(best, OneWalletAddrs{P2SH: true, Key: k, rec: rec})
		}
	}

	for k, rec := range wallet.AllBalancesP2KH {
		ptkh_vals += rec.Value
		ptkh_outs += uint64(len(rec.Unsp))
		if sort_by_cnt && len(rec.Unsp) >= 1000 || !sort_by_cnt && rec.Value >= 1000e8 {
			best = append(best, OneWalletAddrs{Key: k, rec: rec})
		}
	}

	fmt.Println(btc.UintToBtc(ptkh_vals), "BTC in", ptkh_outs, "unspent recs from", len(wallet.AllBalancesP2KH), "P2KH addresses")
	fmt.Println(btc.UintToBtc(ptsh_vals), "BTC in", ptsh_outs, "unspent recs from", len(wallet.AllBalancesP2SH), "P2SH addresses")

	if sort_by_cnt {
		fmt.Println("Addrs with at least 1000 inps:", len(best))
	} else {
		fmt.Println("Addrs with at least 1000 BTC:", len(best))
	}

	sort.Sort(best)

	var pkscr_p2sk [23]byte
	var pkscr_p2kh [25]byte
	var ad *btc.BtcAddr

	pkscr_p2sk[0] = 0xa9
	pkscr_p2sk[1] = 20
	pkscr_p2sk[22] = 0x87

	pkscr_p2kh[0] = 0x76
	pkscr_p2kh[1] = 0xa9
	pkscr_p2kh[2] = 20
	pkscr_p2kh[23] = 0x88
	pkscr_p2kh[24] = 0xac

	for i := 0; i < len(best) && i < cnt; i++ {
		if best[i].P2SH {
			copy(pkscr_p2sk[2:22], best[i].Key[:])
			ad = btc.NewAddrFromPkScript(pkscr_p2sk[:], common.CFG.Testnet)
		} else {
			copy(pkscr_p2kh[3:23], best[i].Key[:])
			ad = btc.NewAddrFromPkScript(pkscr_p2kh[:], common.CFG.Testnet)
		}
		fmt.Println(i+1, ad.String(), btc.UintToBtc(best[i].rec.Value), "BTC in", len(best[i].rec.Unsp), "inputs")
	}
}