Example #1
0
func raw_tx_from_file(fn string) *btc.Tx {
	d, er := ioutil.ReadFile(fn)
	if er != nil {
		fmt.Println(er.Error())
		return nil
	}

	var dat []byte
	hexdump := is_hex_string(d)
	if len(hexdump) >= 2 || (len(hexdump)&1) == 1 {
		dat, _ = hex.DecodeString(hexdump)
	} else {
		if *verbose {
			fmt.Println("Assume binary transaction file")
		}
		dat = d
	}

	tx, txle := btc.NewTx(dat)

	if tx != nil && txle != len(dat) {
		fmt.Println("WARNING: Raw transaction length mismatch", txle, len(dat))
	}

	return tx
}
Example #2
0
func LoadRawTx(buf []byte) (s string) {
	txd, er := hex.DecodeString(string(buf))
	if er != nil {
		txd = buf
	}

	// At this place we should have raw transaction in txd
	tx, le := btc.NewTx(txd)
	if tx == nil || le != len(txd) {
		s += fmt.Sprintln("Could not decode transaction file or it has some extra data")
		return
	}
	tx.Hash = btc.NewSha2Hash(txd)

	var missinginp bool
	var totinp, totout uint64
	s, missinginp, totinp, totout, er = DecodeTx(tx)
	if er != nil {
		return
	}

	network.TxMutex.Lock()
	if missinginp {
		network.TransactionsToSend[tx.Hash.Hash] = &network.OneTxToSend{Tx: tx, Data: txd, Own: 2, Firstseen: time.Now(),
			Volume: totout}
	} else {
		network.TransactionsToSend[tx.Hash.Hash] = &network.OneTxToSend{Tx: tx, Data: txd, Own: 1, Firstseen: time.Now(),
			Volume: totinp, Fee: totinp - totout}
	}
	network.TxMutex.Unlock()
	s += fmt.Sprintln("Transaction added to the memory pool. Please double check its details above.")
	s += fmt.Sprintln("If it does what you intended, you can send it the network.\nUse TxID:", tx.Hash.String())
	return
}
Example #3
0
// Handle incoming "tx" msg
func (c *OneConnection) ParseTxNet(pl []byte) {
	tid := btc.NewSha2Hash(pl)
	NeedThisTx(tid, func() {
		// This body is called with a locked TxMutex
		if uint32(len(pl)) > atomic.LoadUint32(&common.CFG.TXPool.MaxTxSize) {
			common.CountSafe("TxTooBig")
			RejectTx(tid, len(pl), TX_REJECTED_TOO_BIG)
			return
		}
		tx, le := btc.NewTx(pl)
		if tx == nil {
			RejectTx(tid, len(pl), TX_REJECTED_FORMAT)
			c.DoS("TxBroken")
			return
		}
		if le != len(pl) {
			RejectTx(tid, len(pl), TX_REJECTED_LEN_MISMATCH)
			c.DoS("TxLenMismatch")
			return
		}
		if len(tx.TxIn) < 1 {
			RejectTx(tid, len(pl), TX_REJECTED_EMPTY_INPUT)
			c.DoS("TxNoInputs")
			return
		}

		tx.Hash = tid
		select {
		case NetTxs <- &TxRcvd{conn: c, tx: tx, raw: pl}:
			TransactionsPending[tid.BIdx()] = true
		default:
			common.CountSafe("NetTxsFULL")
		}
	})
}
Example #4
0
func raw_tx_from_file(fn string) *btc.Tx {
	dat := utils.GetRawData(fn)
	if dat == nil {
		fmt.Println("Cannot fetch raw transaction data")
		return nil
	}
	tx, txle := btc.NewTx(dat)
	if tx != nil && txle != len(dat) {
		fmt.Println("WARNING: Raw transaction length mismatch", txle, len(dat))
	}
	return tx
}
Example #5
0
func raw_tx_from_file(fn string) *btc.Tx {
	d, er := ioutil.ReadFile(fn)
	if er != nil {
		fmt.Println(er.Error())
		return nil
	}

	dat, er := hex.DecodeString(string(d))
	if er != nil {
		fmt.Println("hex.DecodeString failed - assume binary transaction file")
		dat = d
	}
	tx, txle := btc.NewTx(dat)

	if tx != nil && txle != len(dat) {
		fmt.Println("WARNING: Raw transaction length mismatch", txle, len(dat))
	}

	return tx
}
Example #6
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")
}
Example #7
0
// Handle incomming "tx" msg
func (c *OneConnection) ParseTxNet(pl []byte) {
	tid := btc.NewSha2Hash(pl)
	if uint32(len(pl)) > atomic.LoadUint32(&common.CFG.TXPool.MaxTxSize) {
		common.CountSafe("TxTooBig")
		TransactionsRejected[tid.BIdx()] = NewRejectedTx(tid, len(pl), TX_REJECTED_TOO_BIG)
		return
	}
	NeedThisTx(tid, func() {
		tx, le := btc.NewTx(pl)
		if tx == nil {
			common.CountSafe("TxParseError")
			TransactionsRejected[tid.BIdx()] = NewRejectedTx(tid, len(pl), TX_REJECTED_FORMAT)
			c.DoS()
			return
		}
		if le != len(pl) {
			common.CountSafe("TxParseLength")
			TransactionsRejected[tid.BIdx()] = NewRejectedTx(tid, len(pl), TX_REJECTED_LEN_MISMATCH)
			c.DoS()
			return
		}
		if len(tx.TxIn) < 1 {
			common.CountSafe("TxParseEmpty")
			TransactionsRejected[tid.BIdx()] = NewRejectedTx(tid, len(pl), TX_REJECTED_EMPTY_INPUT)
			c.DoS()
			return
		}

		tx.Hash = tid
		select {
		case NetTxs <- &TxRcvd{conn: c, tx: tx, raw: pl}:
			TransactionsPending[tid.Hash] = true
		default:
			common.CountSafe("NetTxsFULL")
		}
	})
}
Example #8
0
// load the content of the "balance/" folder
func load_balance() {
	var unknownInputs int
	f, e := os.Open("balance/unspent.txt")
	if e != nil {
		println(e.Error())
		os.Exit(1)
	}
	rd := bufio.NewReader(f)
	for {
		l, _, e := rd.ReadLine()
		if len(l) == 0 && e != nil {
			break
		}
		if l[64] == '-' {
			txid := btc.NewUint256FromString(string(l[:64]))
			rst := strings.SplitN(string(l[65:]), " ", 2)
			vout, _ := strconv.ParseUint(rst[0], 10, 32)
			uns := new(btc.TxPrevOut)
			copy(uns.Hash[:], txid.Hash[:])
			uns.Vout = uint32(vout)
			lab := ""
			if len(rst) > 1 {
				lab = rst[1]
			}

			if _, ok := loadedTxs[txid.Hash]; !ok {
				tf, _ := os.Open("balance/" + txid.String() + ".tx")
				if tf != nil {
					siz, _ := tf.Seek(0, os.SEEK_END)
					tf.Seek(0, os.SEEK_SET)
					buf := make([]byte, siz)
					tf.Read(buf)
					tf.Close()
					th := btc.Sha2Sum(buf)
					if bytes.Equal(th[:], txid.Hash[:]) {
						tx, _ := btc.NewTx(buf)
						if tx != nil {
							loadedTxs[txid.Hash] = tx
						} else {
							println("transaction is corrupt:", txid.String())
						}
					} else {
						println("transaction file is corrupt:", txid.String())
						os.Exit(1)
					}
				} else {
					println("transaction file not found:", txid.String())
					os.Exit(1)
				}
			}

			uo := UO(uns)
			fnd := false
			for j := range publ_addrs {
				if publ_addrs[j].Owns(uo.Pk_script) {
					unspentOuts = append(unspentOuts, uns)
					unspentOutsLabel = append(unspentOutsLabel, lab)
					totBtc += UO(uns).Value
					fnd = true
					break
				}
			}

			if !fnd {
				unknownInputs++
				if *verbose {
					fmt.Println(uns.String(), "does not belogn to your wallet - ignore it")
				}
			}

		}
	}
	f.Close()
	fmt.Printf("You have %.8f BTC in %d unspent outputs\n", float64(totBtc)/1e8, len(unspentOuts))
	if unknownInputs > 0 {
		fmt.Printf("WARNING: Some inputs (%d) cannot be spent (-v to print them)\n", unknownInputs)
	}
}
Example #9
0
// load the content of the "balance/" folder
func load_balance(showbalance bool) {
	var unknownInputs, multisigInputs int
	f, e := os.Open("balance/unspent.txt")
	if e != nil {
		println(e.Error())
		return
	}
	rd := bufio.NewReader(f)
	for {
		l, _, e := rd.ReadLine()
		if len(l) == 0 && e != nil {
			break
		}
		if l[64] == '-' {
			txid := btc.NewUint256FromString(string(l[:64]))
			rst := strings.SplitN(string(l[65:]), " ", 2)
			vout, _ := strconv.ParseUint(rst[0], 10, 32)
			uns := new(btc.TxPrevOut)
			copy(uns.Hash[:], txid.Hash[:])
			uns.Vout = uint32(vout)
			lab := ""
			if len(rst) > 1 {
				lab = rst[1]
			}

			if _, ok := loadedTxs[txid.Hash]; !ok {
				tf, _ := os.Open("balance/" + txid.String() + ".tx")
				if tf != nil {
					siz, _ := tf.Seek(0, os.SEEK_END)
					tf.Seek(0, os.SEEK_SET)
					buf := make([]byte, siz)
					tf.Read(buf)
					tf.Close()
					th := btc.Sha2Sum(buf)
					if bytes.Equal(th[:], txid.Hash[:]) {
						tx, _ := btc.NewTx(buf)
						if tx != nil {
							loadedTxs[txid.Hash] = tx
						} else {
							println("transaction is corrupt:", txid.String())
						}
					} else {
						println("transaction file is corrupt:", txid.String())
						os.Exit(1)
					}
				} else {
					println("transaction file not found:", txid.String())
					os.Exit(1)
				}
			}

			unspentOuts = append(unspentOuts, uns)
			unspentOutsLabel = append(unspentOutsLabel, lab)

			// Sum up all the balance and check if we have private key for this input
			uo := UO(uns)
			totBtc += UO(uns).Value

			if !btc.IsP2SH(uo.Pk_script) {
				fnd := false
				for j := range publ_addrs {
					if publ_addrs[j].Owns(uo.Pk_script) {
						fnd = true
						break
					}
				}

				if showbalance && !fnd {
					unknownInputs++
					if *verbose {
						ss := uns.String()
						ss = ss[:8] + "..." + ss[len(ss)-12:]
						fmt.Println(ss, "does not belong to your wallet (cannot sign it)")
					}
				}
			} else {
				if *verbose {
					ss := uns.String()
					ss = ss[:8] + "..." + ss[len(ss)-12:]
					fmt.Println(ss, "belongs to a multisig address")
				}
				multisigInputs++
			}
		}
	}
	f.Close()
	fmt.Printf("You have %.8f BTC in %d unspent outputs. %d inputs are multisig type\n",
		float64(totBtc)/1e8, len(unspentOuts), multisigInputs)
	if showbalance {
		if unknownInputs > 0 {
			fmt.Printf("WARNING: Some inputs (%d) cannot be spent with this password (-v to print them)\n", unknownInputs)
		}
	}
}
Example #10
0
// load the content of the "balance/" folder
func load_balance(showbalance bool) {
	var unknownInputs, multisigInputs int
	f, e := os.Open("balance/unspent.txt")
	if e != nil {
		println(e.Error())
		return
	}
	rd := bufio.NewReader(f)
	for {
		l, _, e := rd.ReadLine()
		if len(l) == 0 && e != nil {
			break
		}
		if l[64] == '-' {
			txid := btc.NewUint256FromString(string(l[:64]))
			rst := strings.SplitN(string(l[65:]), " ", 2)
			vout, _ := strconv.ParseUint(rst[0], 10, 32)
			uns := new(btc.TxPrevOut)
			copy(uns.Hash[:], txid.Hash[:])
			uns.Vout = uint32(vout)
			lab := ""
			if len(rst) > 1 {
				lab = rst[1]
			}

			str := string(l)
			if sti := strings.Index(str, "_StealthC:"); sti != -1 {
				c, e := hex.DecodeString(str[sti+10 : sti+10+64])
				if e != nil {
					fmt.Println("ERROR at stealth", txid.String(), vout, e.Error())
				} else {
					// add a new key to the wallet
					sec := btc.DeriveNextPrivate(first_seed[:], c)
					is_stealth[len(priv_keys)] = true
					priv_keys = append(priv_keys, sec)
					labels = append(labels, lab)
					pub_key := btc.PublicFromPrivate(sec, true)
					publ_addrs = append(publ_addrs, btc.NewAddrFromPubkey(pub_key, btc.AddrVerPubkey(*testnet)))
					compressed_key = append(compressed_key, true) // stealth keys are always compressed
				}
			}

			if _, ok := loadedTxs[txid.Hash]; !ok {
				tf, _ := os.Open("balance/" + txid.String() + ".tx")
				if tf != nil {
					siz, _ := tf.Seek(0, os.SEEK_END)
					tf.Seek(0, os.SEEK_SET)
					buf := make([]byte, siz)
					tf.Read(buf)
					tf.Close()
					th := btc.Sha2Sum(buf)
					if bytes.Equal(th[:], txid.Hash[:]) {
						tx, _ := btc.NewTx(buf)
						if tx != nil {
							loadedTxs[txid.Hash] = tx
						} else {
							println("transaction is corrupt:", txid.String())
						}
					} else {
						println("transaction file is corrupt:", txid.String())
						os.Exit(1)
					}
				} else {
					println("transaction file not found:", txid.String())
					os.Exit(1)
				}
			}

			// Sum up all the balance and check if we have private key for this input
			uo := UO(uns)

			add_it := true

			if !btc.IsP2SH(uo.Pk_script) {
				fnd := false
				for j := range publ_addrs {
					if publ_addrs[j].Owns(uo.Pk_script) {
						fnd = true
						break
					}
				}

				if !fnd {
					if *onlvalid {
						add_it = false
					}
					if showbalance {
						unknownInputs++
						if *verbose {
							ss := uns.String()
							ss = ss[:8] + "..." + ss[len(ss)-12:]
							fmt.Println(ss, "does not belong to your wallet (cannot sign it)")
						}
					}
				}
			} else {
				if *onlvalid {
					add_it = false
				}
				if *verbose {
					ss := uns.String()
					ss = ss[:8] + "..." + ss[len(ss)-12:]
					fmt.Println(ss, "belongs to a multisig address")
				}
				multisigInputs++
			}

			if add_it {
				unspentOuts = append(unspentOuts, uns)
				unspentOutsLabel = append(unspentOutsLabel, lab)
				totBtc += UO(uns).Value
			}
		}
	}
	f.Close()
	fmt.Printf("You have %.8f BTC in %d unspent outputs. %d inputs are multisig type\n",
		float64(totBtc)/1e8, len(unspentOuts), multisigInputs)
	if showbalance {
		if unknownInputs > 0 {
			fmt.Printf("WARNING: Some inputs (%d) cannot be spent with this password (-v to print them)\n", unknownInputs)
		}
	}
}