Пример #1
0
func DecodeTx(tx *btc.Tx) (s string, missinginp bool, totinp, totout uint64, e error) {
	s += fmt.Sprintln("Transaction details (for your information):")
	s += fmt.Sprintln(len(tx.TxIn), "Input(s):")
	for i := range tx.TxIn {
		s += fmt.Sprintf(" %3d %s", i, tx.TxIn[i].Input.String())
		var po *btc.TxOut

		inpid := btc.NewUint256(tx.TxIn[i].Input.Hash[:])
		if txinmem, ok := network.TransactionsToSend[inpid.BIdx()]; ok {
			s += fmt.Sprint(" mempool")
			if int(tx.TxIn[i].Input.Vout) >= len(txinmem.TxOut) {
				s += fmt.Sprintf(" - Vout TOO BIG (%d/%d)!", int(tx.TxIn[i].Input.Vout), len(txinmem.TxOut))
			} else {
				po = txinmem.TxOut[tx.TxIn[i].Input.Vout]
			}
		} else {
			po, _ = common.BlockChain.Unspent.UnspentGet(&tx.TxIn[i].Input)
			if po != nil {
				s += fmt.Sprintf("%8d", po.BlockHeight)
			}
		}
		if po != nil {
			ok := btc.VerifyTxScript(tx.TxIn[i].ScriptSig, po.Pk_script, i, tx, true)
			if !ok {
				s += fmt.Sprintln("\nERROR: The transacion does not have a valid signature.")
				e = errors.New("Invalid signature")
				return
			}
			totinp += po.Value
			s += fmt.Sprintf(" %15.8f BTC @ %s\n", float64(po.Value)/1e8,
				btc.NewAddrFromPkScript(po.Pk_script, common.Testnet).String())
		} else {
			s += fmt.Sprintln(" - UNKNOWN INPUT")
			missinginp = true
		}
	}
	s += fmt.Sprintln(len(tx.TxOut), "Output(s):")
	for i := range tx.TxOut {
		totout += tx.TxOut[i].Value
		adr := btc.NewAddrFromPkScript(tx.TxOut[i].Pk_script, common.Testnet)
		if adr != nil {
			s += fmt.Sprintf(" %15.8f BTC to adr %s\n", float64(tx.TxOut[i].Value)/1e8, adr.String())
		} else {
			s += fmt.Sprintf(" %15.8f BTC to scr %s\n", float64(tx.TxOut[i].Value)/1e8, hex.EncodeToString(tx.TxOut[i].Pk_script))
		}
	}
	if missinginp {
		s += fmt.Sprintln("WARNING: There are missing inputs and we cannot calc input BTC amount.")
		s += fmt.Sprintln("If there is somethign wrong with this transaction, you can loose money...")
	} else {
		s += fmt.Sprintf("All OK: %.8f BTC in -> %.8f BTC out, with %.8f BTC fee\n", float64(totinp)/1e8,
			float64(totout)/1e8, float64(totinp-totout)/1e8)
	}
	return
}
Пример #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 := btc.VerifyTxScript(tx.TxIn[i].ScriptSig, po.Pk_script, i, tx, true)
				if !ok {
					w.Write([]byte("<status>Script FAILED</status>"))
				} else {
					w.Write([]byte("<status>OK</status>"))
				}
				fmt.Fprint(w, "<value>", po.Value, "</value>")
				fmt.Fprint(w, "<addr>", btc.NewAddrFromPkScript(po.Pk_script, common.Testnet).String(), "</addr>")
				fmt.Fprint(w, "<block>", po.BlockHeight, "</block>")
			} else {
				w.Write([]byte("<status>UNKNOWN INPUT</status>"))
			}
			w.Write([]byte("</input>"))
		}
		w.Write([]byte("</inputs>"))

		w.Write([]byte("<outputs>"))
		for i := range tx.TxOut {
			w.Write([]byte("<output>"))
			fmt.Fprint(w, "<value>", tx.TxOut[i].Value, "</value>")
			adr := btc.NewAddrFromPkScript(tx.TxOut[i].Pk_script, common.Testnet)
			if adr != nil {
				fmt.Fprint(w, "<addr>", adr.String(), "</addr>")
			} else {
				fmt.Fprint(w, "<addr>", "scr:"+hex.EncodeToString(tx.TxOut[i].Pk_script), "</addr>")
			}
			w.Write([]byte("</output>"))
		}
		w.Write([]byte("</outputs>"))
	} else {
		w.Write([]byte("<status>Not found</status>"))
	}
	w.Write([]byte("</tx>"))
}
Пример #3
0
// sign raw transaction with all the keys we have
func dump_raw_tx() {
	tx := raw_tx_from_file(*dumptxfn)
	if tx == nil {
		fmt.Println("ERROR: Cannot decode the raw transaction")
		return
	}

	fmt.Println("Version:", tx.Version)
	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 {
			dump_sigscript(tx.TxIn[i].ScriptSig)
		}
	}
	fmt.Println("TX OUT cnt:", len(tx.TxOut))
	for i := range tx.TxOut {
		fmt.Printf("%4d) %20s BTC to ", i, btc.UintToBtc(tx.TxOut[i].Value))
		addr := btc.NewAddrFromPkScript(tx.TxOut[i].Pk_script, *testnet)
		if addr != nil {
			fmt.Println("address", addr.String())
		} else {
			fmt.Println("Pk_script", hex.EncodeToString(tx.TxOut[i].Pk_script))
		}
	}
	fmt.Println("Lock Time:", tx.Lock_time)
}
Пример #4
0
// This is called while accepting the block (from the chain's thread)
func TxNotify(idx *btc.TxPrevOut, valpk *btc.TxOut) {
	var update_wallet bool

	mutex_bal.Lock()
	defer mutex_bal.Unlock()

	if valpk != nil {
		// Extract hash160 from pkscript
		adr := btc.NewAddrFromPkScript(valpk.Pk_script, common.Testnet)
		if adr == nil {
			return // We do not monitor this address
		}

		if rec, ok := CachedAddrs[adr.Hash160]; ok {
			rec.Value += valpk.Value
			utxo := new(btc.OneUnspentTx)
			utxo.TxPrevOut = *idx
			utxo.Value = valpk.Value
			utxo.MinedAt = valpk.BlockHeight
			utxo.BtcAddr = CacheUnspent[rec.CacheIndex].BtcAddr
			CacheUnspent[rec.CacheIndex].AllUnspentTx = append(CacheUnspent[rec.CacheIndex].AllUnspentTx, utxo)
			CacheUnspentIdx[po2idx(idx)] = &OneCachedUnspentIdx{Index: rec.CacheIndex, Record: utxo}
			if rec.InWallet {
				update_wallet = true
			}
		}
	} else {
		ii := po2idx(idx)
		if ab, present := CacheUnspentIdx[ii]; present {
			adrec := CacheUnspent[ab.Index]
			//println("removing", idx.String())
			rec := CachedAddrs[adrec.BtcAddr.Hash160]
			if rec == nil {
				panic("rec not found for " + adrec.BtcAddr.String())
			}
			rec.Value -= ab.Record.Value
			if rec.InWallet {
				update_wallet = true
			}
			for j := range adrec.AllUnspentTx {
				if adrec.AllUnspentTx[j] == ab.Record {
					//println("found it at index", j)
					adrec.AllUnspentTx = append(adrec.AllUnspentTx[:j], adrec.AllUnspentTx[j+1:]...)
					break
				}
			}
			delete(CacheUnspentIdx, ii)
		}
	}

	if MyWallet != nil && update_wallet {
		MyBalance = nil
		for i := range MyWallet.Addrs {
			rec, _ := CachedAddrs[MyWallet.Addrs[i].Hash160]
			MyBalance = append(MyBalance, CacheUnspent[rec.CacheIndex].AllUnspentTx...)
		}
		sort_and_sum()
		BalanceChanged = true
	}
}
Пример #5
0
func load_tx(par string) {
	txd, er := hex.DecodeString(par)
	if er != nil {
		println(er.Error())
	}
	tx, le := btc.NewTx(txd)
	if le != len(txd) {
		fmt.Println("WARNING: Tx length mismatch", le, len(txd))
	}
	txid := btc.NewSha2Hash(txd)
	fmt.Println(len(tx.TxIn), "inputs:")
	var totinp, totout uint64
	var missinginp bool
	for i := range tx.TxIn {
		fmt.Printf(" %3d %s", i, tx.TxIn[i].Input.String())
		po, _ := BlockChain.Unspent.UnspentGet(&tx.TxIn[i].Input)
		if po != nil {
			totinp += po.Value
			fmt.Printf(" %15.8f BTC @ %s\n", float64(po.Value)/1e8,
				btc.NewAddrFromPkScript(po.Pk_script, AddrVersion).String())
		} else {
			fmt.Println(" * no such unspent in the blockchain *")
			missinginp = true
		}
	}
	fmt.Println(len(tx.TxOut), "outputs:")
	for i := range tx.TxOut {
		totout += tx.TxOut[i].Value
		fmt.Printf(" %15.8f BTC to %s\n", float64(tx.TxOut[i].Value)/1e8,
			btc.NewAddrFromPkScript(tx.TxOut[i].Pk_script, AddrVersion).String())
	}
	if missinginp {
		fmt.Println("WARNING: There are missing inputs, so you cannot calc input BTC amount")
	} else {
		fmt.Printf("%.8f BTC in -> %.8f BTC out, with %.8f BTC fee\n", float64(totinp)/1e8,
			float64(totout)/1e8, float64(totinp-totout)/1e8)
	}
	TransactionsToSend[txid.Hash] = txd
	fmt.Println("Transaction", txid.String(), "stored in the memory pool")
	fmt.Println("Execute 'stx " + txid.String() + "' to send it out")
}
Пример #6
0
// dump hashes to be signed
func dump_hashes_to_sign(tx *btc.Tx) {
	for in := range tx.TxIn {
		uo := UO(unspentOuts[in])
		if uo == nil {
			println("Unknown content of unspent input number", in)
			os.Exit(1)
		}
		pubad := btc.NewAddrFromPkScript(uo.Pk_script, *testnet)
		hash := tx.SignatureHash(uo.Pk_script, in, btc.SIGHASH_ALL)
		fmt.Printf("Input #%d:\n\tHash : %s\n\tAddr : %s\n", in, hex.EncodeToString(hash), pubad.String())
	}
}
Пример #7
0
// This is called while accepting the block (from teh chain's thread)
func TxNotify(idx *btc.TxPrevOut, valpk *btc.TxOut) {
	var update_wallet bool

	mutex_bal.Lock()
	defer mutex_bal.Unlock()

	if valpk != nil {
		// Extract hash160 from pkscript
		adr := btc.NewAddrFromPkScript(valpk.Pk_script, common.Testnet)
		if adr == nil {
			return // We do not monitor this address
		}

		if rec, ok := CachedAddrs[adr.Hash160]; ok {
			rec.Value += valpk.Value
			utxo := btc.OneUnspentTx{TxPrevOut: *idx, Value: valpk.Value,
				MinedAt: valpk.BlockHeight, BtcAddr: CacheUnspent[rec.CacheIndex].BtcAddr}
			CacheUnspent[rec.CacheIndex].AllUnspentTx = append(CacheUnspent[rec.CacheIndex].AllUnspentTx, utxo)
			CacheUnspentIdx[po2idx(idx)] = [2]uint{rec.CacheIndex, uint(len(CacheUnspent[rec.CacheIndex].AllUnspentTx)) - 1}
			if rec.InWallet {
				update_wallet = true
			}
		}
	} else {
		ii := po2idx(idx)
		if ab, present := CacheUnspentIdx[ii]; present {
			adrec := CacheUnspent[ab[0]]

			rec := CachedAddrs[adrec.BtcAddr.Hash160]
			rec.Value -= adrec.AllUnspentTx[ab[1]].Value
			if rec.InWallet {
				update_wallet = true
			}

			adrec.AllUnspentTx = append(adrec.AllUnspentTx[:ab[1]], adrec.AllUnspentTx[ab[1]+1:]...)

			delete(CacheUnspentIdx, ii)
		}
	}

	if MyWallet != nil && update_wallet {
		MyBalance = nil
		for i := range MyWallet.Addrs {
			rec, _ := CachedAddrs[MyWallet.Addrs[i].Hash160]
			MyBalance = append(MyBalance, CacheUnspent[rec.CacheIndex].AllUnspentTx...)
		}
		BalanceChanged = true
	}
}
Пример #8
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("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 {
				dump_sigscript(tx.TxIn[i].ScriptSig)
			} else {
				unsigned++
			}
		}
	}
	fmt.Println("TX OUT cnt:", len(tx.TxOut))
	for i := range tx.TxOut {
		fmt.Printf("%4d) %20s BTC to ", i, btc.UintToBtc(tx.TxOut[i].Value))
		addr := btc.NewAddrFromPkScript(tx.TxOut[i].Pk_script, *testnet)
		if addr != nil {
			fmt.Println("address", addr.String())
		} else {
			fmt.Println("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("Number of unsigned inputs:", unsigned)
		} else {
			fmt.Println("All the inputs seems to be signed")
		}
	}
}
Пример #9
0
func main() {
	fmt.Println("Gocoin FetchBalnace version", btc.SourcesTag)

	if len(os.Args) < 2 {
		print_help()
		return
	}

	var addrs []*btc.BtcAddr

	if len(os.Args) == 2 {
		fi, er := os.Stat(os.Args[1])
		if er == nil && fi.Size() > 10 && !fi.IsDir() {
			wal := wallet.NewWallet(os.Args[1])
			if wal != nil {
				fmt.Println("Found", len(wal.Addrs), "address(es) in", wal.FileName)
				addrs = wal.Addrs
			}
		}
	}

	if len(addrs) == 0 {
		for i := 1; i < len(os.Args); i++ {
			a, e := btc.NewAddrFromString(os.Args[i])
			if e != nil {
				println(os.Args[i], ": ", e.Error())
				return
			} else {
				addrs = append(addrs, a)
			}
		}
	}

	if len(addrs) == 0 {
		print_help()
		return
	}

	url := "http://blockchain.info/unspent?active="
	for i := range addrs {
		if i > 0 {
			url += "|"
		}
		url += addrs[i].String()
	}

	var sum, outcnt uint64
	r, er := http.Get(url)
	if er == nil && r.StatusCode == 200 {
		defer r.Body.Close()
		c, _ := ioutil.ReadAll(r.Body)
		var r restype
		er = json.Unmarshal(c[:], &r)
		if er == nil {
			os.RemoveAll("balance/")
			os.Mkdir("balance/", 0700)
			unsp, _ := os.Create("balance/unspent.txt")
			for i := 0; i < len(r.Unspent_outputs); i++ {
				pkscr, _ := hex.DecodeString(r.Unspent_outputs[i].Script)
				b58adr := "???"
				if pkscr != nil {
					ba := btc.NewAddrFromPkScript(pkscr, btc.ADDRVER_BTC)
					if ba != nil {
						b58adr = ba.String()
					}
				}
				txidlsb, _ := hex.DecodeString(r.Unspent_outputs[i].Tx_hash)
				if txidlsb != nil {
					txid := btc.NewUint256(txidlsb)
					if GetTx(txid, int(r.Unspent_outputs[i].Tx_output_n)) {
						fmt.Fprintf(unsp, "%s-%03d # %.8f @ %s, %d confs\n",
							txid.String(), r.Unspent_outputs[i].Tx_output_n,
							float64(r.Unspent_outputs[i].Value)/1e8,
							b58adr, r.Unspent_outputs[i].Confirmations)
						sum += r.Unspent_outputs[i].Value
						outcnt++
					} else {
						fmt.Printf(" - cannot fetch %s-%03d\n", txid.String(), r.Unspent_outputs[i].Tx_output_n)
					}
				}
			}
			unsp.Close()
			if outcnt > 0 {
				fmt.Printf("Total %.8f BTC in %d unspent outputs.\n", float64(sum)/1e8, outcnt)
				fmt.Println("The data has been stored in 'balance' folder.")
				fmt.Println("Use it with the wallet app to spend any of it.")
			} else {
				fmt.Println("The fateched balance is empty.")
			}
		} else {
			fmt.Println("Unspent json.Unmarshal", er.Error())
		}
	} else {
		if er != nil {
			fmt.Println("Unspent ", er.Error())
		} else {
			fmt.Println("Unspent HTTP StatusCode", r.StatusCode)
		}
	}
}