Beispiel #1
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")
		}
	})
}
Beispiel #2
0
// Download raw transaction from a web server (try one after another)
func GetTxFromWeb(txid *btc.Uint256) (raw []byte) {
	raw = GetTxFromWebBTC(txid)
	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
}
Beispiel #3
0
func write_tx_file(tx *btc.Tx) {
	signedrawtx := tx.Serialize()
	tx.Hash = btc.NewSha2Hash(signedrawtx)

	hs := tx.Hash.String()
	fmt.Println(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")
	}
}
Beispiel #4
0
func raw_tx_from_file(fn string) *btc.Tx {
	dat := sys.GetRawData(fn)
	if dat == nil {
		fmt.Println("Cannot fetch raw transaction data")
		return nil
	}
	tx, txle := btc.NewTx(dat)
	if tx != nil {
		tx.Hash = btc.NewSha2Hash(dat)
		if txle != len(dat) {
			fmt.Println("WARNING: Raw transaction length mismatch", txle, len(dat))
		}
	}
	return tx
}
Beispiel #5
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)

	network.TxMutex.Lock()
	defer network.TxMutex.Unlock()
	if _, ok := network.TransactionsToSend[tx.Hash.BIdx()]; ok {
		s += fmt.Sprintln("TxID", tx.Hash.String(), "was already in the pool")
		return
	}

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

	if missinginp {
		network.TransactionsToSend[tx.Hash.BIdx()] = &network.OneTxToSend{Tx: tx, Data: txd, Own: 2, Firstseen: time.Now(),
			Volume: totout}
	} else {
		network.TransactionsToSend[tx.Hash.BIdx()] = &network.OneTxToSend{Tx: tx, Data: txd, Own: 1, Firstseen: time.Now(),
			Volume: totinp, Fee: totinp - totout}
	}
	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
}
Beispiel #6
0
func push_tx(rawtx string) {
	dat := sys.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)
	}
}
Beispiel #7
0
func main() {
	if len(os.Args)<2 {
		fmt.Println("Specify a path to folder containig blockchain.dat and blockchain.new")
		fmt.Println("Output bootstrap.dat file will be written in the current folder.")
		return
	}

	blks := chain.NewBlockDB(os.Args[1])
	if blks==nil {
		return
	}
	fmt.Println("Loading block index...")
	bidx = make(map[[32]byte] *chain.BlockTreeNode, 300e3)
	blks.LoadBlockIndex(nil, walk)

	var tail, nd *chain.BlockTreeNode
	var genesis_block_hash *btc.Uint256
	for _, v := range bidx {
		if v==tail {
			// skip root block (should be only one)
			continue
		}

		par_hash := btc.NewUint256(v.BlockHeader[4:36])
		par, ok := bidx[par_hash.Hash]
		if !ok {
			genesis_block_hash = par_hash
		} else {
			v.Parent = par
			if tail==nil || v.Height > tail.Height {
				tail = v
			}
		}
	}

	if genesis_block_hash == nil {
		println("genesis_block_hash not found")
		return
	}

	var magic []byte

	gen_bin, _ := hex.DecodeString(GenesisBitcoin)
	tmp := btc.NewSha2Hash(gen_bin[:80])
	if genesis_block_hash.Equal(tmp) {
		println("Bitcoin genesis block")
		magic = []byte{0xF9,0xBE,0xB4,0xD9}
	}


	if magic==nil {
		gen_bin, _ := hex.DecodeString(GenesisTestnet)
		tmp = btc.NewSha2Hash(gen_bin[:80])
		if genesis_block_hash.Equal(tmp) {
			println("Testnet3 genesis block")
			magic = []byte{0x0B,0x11,0x09,0x07}
		}
	}

	if magic==nil {
		println("Unknow genesis block", genesis_block_hash.String())
		println("Aborting since cannot figure out the magic bytes")
		return
	}

	var total_data, curr_data int64

	for nd=tail; nd.Parent!=nil; {
		nd.Parent.Childs = []*chain.BlockTreeNode{nd}
		total_data += int64(nd.BlockSize)
		nd = nd.Parent
	}
	fmt.Println("Writting bootstrap.dat, height", tail.Height, "  magic", hex.EncodeToString(magic))
	f, _ := os.Create("bootstrap.dat")
	f.Write(magic)
	binary.Write(f, binary.LittleEndian, uint32(len(gen_bin)))
	f.Write(gen_bin)
	for {
		bl, _, _ := blks.BlockGet(nd.BlockHash)
		f.Write(magic)
		binary.Write(f, binary.LittleEndian, uint32(len(bl)))
		f.Write(bl)
		curr_data += int64(nd.BlockSize)
		if (nd.Height&0xfff)==0 {
			fmt.Printf("\r%.1f%%...", 100*float64(curr_data)/float64(total_data))
		}
		if len(nd.Childs)==0 {
			break
		}
		nd = nd.Childs[0]
	}
	fmt.Println("\rDone           ")
}
Beispiel #8
0
// 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
}
Beispiel #9
0
func (c *one_net_conn) block(d []byte) {
	atomic.AddUint64(&DlBytesDownloaded, uint64(len(d)))

	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("BNOT")
		//fmt.Println(h.String(), "- already received", bip)
		return
	}
	//fmt.Println(h.String(), "- new", bip.Height)
	COUNTER("BYES")

	delete(bip.Conns, c.id)
	c.Lock()
	c.inprogress--
	c.Unlock()
	blocksize_update(len(d))

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

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

	delete(BlocksToGet, bip.Height)
	delete(BlocksInProgress, h.Hash)
	if len(BlocksInProgress) == 0 {
		EmptyInProgressCnt++
	}

	//println("got-", bip.Height, BlocksComplete+1)
	if BlocksComplete+1 == bip.Height {
		BlocksComplete++
		BlockQueue <- bl
		for {
			bl = BlocksCached[BlocksComplete+1]
			if bl == nil {
				break
			}
			BlocksComplete++
			delete(BlocksCached, BlocksComplete)
			BlocksCachedSize -= uint64(len(bl.Raw))
			BlockQueue <- bl
		}
	} else {
		BlocksCached[bip.Height] = bl
		BlocksCachedSize += uint64(len(d))
	}
}