예제 #1
0
파일: usif.go 프로젝트: johtso/gocoin
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
}
예제 #2
0
파일: txpool.go 프로젝트: vipwzw/gocoin
// 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")
		}
	})
}
예제 #3
0
파일: fetchtx.go 프로젝트: shepelt/gocoin
// Download raw transaction from a web server (try one after another)
func GetTxFromWeb(txid *btc.Uint256) (raw []byte) {
	if raw != nil && txid.Equal(btc.NewSha2Hash(raw)) {
		//println("GetTxFromWebBTC - OK")
		return
	}

	raw = GetTxFromBlockrIo(txid)
	if raw != nil && txid.Equal(btc.NewSha2Hash(raw)) {
		//println("GetTxFromBlockrIo - OK")
		return
	}

	raw, _ = GetTxFromExplorer(txid)
	if raw != nil && txid.Equal(btc.NewSha2Hash(raw)) {
		//println("GetTxFromExplorer - OK")
		return
	}

	return
}
예제 #4
0
파일: signtx.go 프로젝트: vipwzw/gocoin
func write_tx_file(tx *btc.Tx) {
	signedrawtx := tx.Serialize()
	tx.Hash = btc.NewSha2Hash(signedrawtx)

	hs := tx.Hash.String()
	fmt.Println("TxID", hs)

	f, _ := os.Create(hs[:8] + ".txt")
	if f != nil {
		f.Write([]byte(hex.EncodeToString(signedrawtx)))
		f.Close()
		fmt.Println("Transaction data stored in", hs[:8]+".txt")
	}
}
예제 #5
0
파일: ping.go 프로젝트: Bitoy/gocoin
func (c *one_net_conn) block_pong(d []byte) {
	if len(d) > 80 {
		c.ping.Lock()
		defer c.ping.Unlock()
		if c.ping.lastBlock != nil {
			c.ping.bytes += uint(len(d))
			h := btc.NewSha2Hash(d[:80])
			if h.Equal(c.ping.lastBlock) {
				//fmt.Println(c.peerip, "bl_pong", c.ping.seq, c.ping.bytes, time.Now().Sub(c.ping.timeSent))
				c.ping.lastBlock = nil
				c.ping.bytes = 0
				c.store_ping_result()
			}
		}
	}
}
예제 #6
0
func GetTx(txid *btc.Uint256, vout int) bool {
	r, er := http.Get("http://blockexplorer.com/rawtx/" + txid.String())
	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 {
			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
				tx.TxIn[i].ScriptSig, _ = btc.DecodeScript(txx.In[i].ScriptSig)
				tx.TxIn[i].Sequence = 0xffffffff
			}
			tx.TxOut = make([]*btc.TxOut, len(txx.Out))
			for i := range txx.Out {
				tx.TxOut[i] = new(btc.TxOut)
				tx.TxOut[i].Value = btc.ParseValue(txx.Out[i].Value)
				tx.TxOut[i].Pk_script, _ = btc.DecodeScript(txx.Out[i].ScriptPubKey)
			}
			tx.Lock_time = txx.Lock_time
			rawtx := tx.Serialize()
			curid := btc.NewSha2Hash(rawtx)
			if !curid.Equal(txid) {
				fmt.Println("The downloaded transaction does not match its ID.")
				return false
			}
			ioutil.WriteFile("balance/"+curid.String()+".tx", rawtx, 0666)
			return true
		} else {
			fmt.Println("json.Unmarshal:", er.Error())
		}
	} else {
		if er != nil {
			fmt.Println("http.Get:", er.Error())
		} else {
			fmt.Println("StatusCode=", r.StatusCode)
		}
	}
	return false
}
예제 #7
0
파일: blks.go 프로젝트: vipwzw/gocoin
func (c *one_net_conn) block(d []byte) {
	BlocksMutex.Lock()
	defer BlocksMutex.Unlock()
	h := btc.NewSha2Hash(d[:80])

	c.Lock()
	c.last_blk_rcvd = time.Now()
	c.Unlock()

	bip := BlocksInProgress[h.Hash]
	if bip == nil || !bip.Conns[c.id] {
		COUNTER("UNEX")
		//fmt.Println(h.String(), "- already received", bip)
		return
	}

	delete(bip.Conns, c.id)
	c.Lock()
	c.inprogress--
	c.Unlock()
	atomic.AddUint64(&DlBytesDownloaded, uint64(len(d)))
	blocksize_update(len(d))

	bl, er := btc.NewBlock(d)
	if er != nil {
		fmt.Println(c.peerip, "-", er.Error())
		c.setbroken(true)
		return
	}

	bl.BuildTxList()
	if !bytes.Equal(btc.GetMerkel(bl.Txs), bl.MerkleRoot()) {
		fmt.Println(c.peerip, " - MerkleRoot mismatch at block", bip.Height)
		c.setbroken(true)
		return
	}

	BlocksCachedSize += uint(len(d))
	BlocksCached[bip.Height] = bl
	delete(BlocksToGet, bip.Height)
	delete(BlocksInProgress, h.Hash)

	//fmt.Println("  got block", height)
}
예제 #8
0
파일: main.go 프로젝트: spartacusX/gocoin
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")
}
예제 #9
0
파일: txpool.go 프로젝트: johtso/gocoin
// 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")
		}
	})
}
예제 #10
0
파일: goc.go 프로젝트: vipwzw/gocoin
func push_tx(rawtx string) {
	dat := utils.GetRawData(rawtx)
	if dat == nil {
		println("Cannot fetch the raw transaction data (specify hexdump or filename)")
		return
	}

	val := make(url.Values)
	val["rawtx"] = []string{hex.EncodeToString(dat)}

	r, er := http.PostForm(HOST+"txs", val)
	if er != nil {
		println(er.Error())
		os.Exit(1)
	}
	if r.StatusCode == 200 {
		defer r.Body.Close()
		res, _ := ioutil.ReadAll(r.Body)
		if len(res) > 100 {
			txid := btc.NewSha2Hash(dat)
			fmt.Println("TxID", txid.String(), "loaded")

			http_get(HOST + "cfg") // get SID
			//fmt.Println("sid", SID)

			u, _ := url.Parse(HOST + "txs2s.xml")
			ps := url.Values{}
			ps.Add("sid", SID)
			ps.Add("send", txid.String())
			u.RawQuery = ps.Encode()
			http_get(u.String())
		}
	} else {
		println("http.Post returned code", r.StatusCode)
		os.Exit(1)
	}
}
예제 #11
0
파일: fetchtx.go 프로젝트: vipwzw/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
}
예제 #12
0
파일: wallet.go 프로젝트: spartacusX/gocoin
// 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
	var inpcnt uint
	for inpcnt = 0; inpcnt < uint(len(unspentOuts)); inpcnt++ {
		uo := UO(unspentOuts[inpcnt])
		// add the input to our transaction:
		tin := new(btc.TxIn)
		tin.Input = *unspentOuts[inpcnt]
		tin.Sequence = 0xffffffff
		tx.TxIn = append(tx.TxIn, tin)

		btcsofar += uo.Value
		if btcsofar >= spendBtc+feeBtc {
			break
		}
	}
	changeBtc = btcsofar - (spendBtc + feeBtc)
	fmt.Printf("Spending %d out of %d outputs...\n", inpcnt+1, len(unspentOuts))

	// Build transaction outputs:
	tx.TxOut = make([]*btc.TxOut, len(sendTo))
	for o := range sendTo {
		tx.TxOut[o] = &btc.TxOut{Value: sendTo[o].amount, Pk_script: sendTo[o].addr.OutScript()}
	}

	if changeBtc > 0 {
		// Add one more output (with the change)
		tx.TxOut = append(tx.TxOut, &btc.TxOut{Value: changeBtc, Pk_script: get_change_addr().OutScript()})
	}

	//fmt.Println("Unsigned:", hex.EncodeToString(tx.Serialize()))

	for in := range tx.TxIn {
		uo := UO(unspentOuts[in])
		var found bool
		for j := range publ_addrs {
			if publ_addrs[j].Owns(uo.Pk_script) {
				pub_key, e := btc.NewPublicKey(publ_addrs[j].Pubkey)
				if e != nil {
					println("NewPublicKey:", e.Error(), "\007")
					os.Exit(1)
				}

				// Load the key (private and public)
				var key ecdsa.PrivateKey
				key.D = new(big.Int).SetBytes(priv_keys[j][:])
				key.PublicKey = pub_key.PublicKey

				//Calculate proper transaction hash
				h := tx.SignatureHash(uo.Pk_script, in, btc.SIGHASH_ALL)
				//fmt.Println("SignatureHash:", btc.NewUint256(h).String())

				// Sign
				r, s, err := ecdsa.Sign(rand.Reader, &key, h)
				if err != nil {
					println("Sign:", err.Error(), "\007")
					os.Exit(1)
				}
				rb := r.Bytes()
				sb := s.Bytes()

				if rb[0] >= 0x80 { // I thinnk this is needed, thought I am not quite sure... :P
					rb = append([]byte{0x00}, rb...)
				}

				if sb[0] >= 0x80 { // I thinnk this is needed, thought I am not quite sure... :P
					sb = append([]byte{0x00}, sb...)
				}

				// Output the signing result into a buffer, in format expected by bitcoin protocol
				busig := new(bytes.Buffer)
				busig.WriteByte(0x30)
				busig.WriteByte(byte(4 + len(rb) + len(sb)))
				busig.WriteByte(0x02)
				busig.WriteByte(byte(len(rb)))
				busig.Write(rb)
				busig.WriteByte(0x02)
				busig.WriteByte(byte(len(sb)))
				busig.Write(sb)
				busig.WriteByte(0x01) // hash type

				// Output the signature and the public key into tx.ScriptSig
				buscr := new(bytes.Buffer)
				buscr.WriteByte(byte(busig.Len()))
				buscr.Write(busig.Bytes())

				buscr.WriteByte(byte(len(publ_addrs[j].Pubkey)))
				buscr.Write(publ_addrs[j].Pubkey)

				// assign:
				tx.TxIn[in].ScriptSig = buscr.Bytes()

				found = true
				break
			}
		}
		if !found {
			fmt.Println("You do not have private key for input number", hex.EncodeToString(uo.Pk_script), "\007")
			os.Exit(1)
		}
	}

	rawtx := tx.Serialize()
	tx.Hash = btc.NewSha2Hash(rawtx)

	hs := tx.Hash.String()
	fmt.Println(hs)

	f, _ := os.Create(hs[:8] + ".txt")
	if f != nil {
		f.Write([]byte(hex.EncodeToString(rawtx)))
		f.Close()
		fmt.Println("Transaction data stored in", hs[:8]+".txt")
	}

	f, _ = os.Create("balance/unspent.txt")
	if f != nil {
		for j := uint(0); j < uint(len(unspentOuts)); j++ {
			if j > inpcnt {
				fmt.Fprintln(f, unspentOuts[j], unspentOutsLabel[j])
			}
		}
		fmt.Println(inpcnt, "spent output(s) removed from 'balance/unspent.txt'")

		var addback int
		for out := range tx.TxOut {
			for j := range publ_addrs {
				if publ_addrs[j].Owns(tx.TxOut[out].Pk_script) {
					fmt.Fprintf(f, "%s-%03d # %.8f / %s\n", tx.Hash.String(), out,
						float64(tx.TxOut[out].Value)/1e8, publ_addrs[j].String())
					addback++
				}
			}
		}
		f.Close()
		if addback > 0 {
			f, _ = os.Create("balance/" + hs + ".tx")
			if f != nil {
				f.Write(rawtx)
				f.Close()
			}
			fmt.Println(addback, "new output(s) appended to 'balance/unspent.txt'")
		}
	}
}