예제 #1
0
파일: net.go 프로젝트: spartacusX/gocoin
func (c *oneConnection) ProcessGetBlocks(pl []byte) {
	b := bytes.NewReader(pl)
	var ver uint32
	e := binary.Read(b, binary.LittleEndian, &ver)
	if e != nil {
		println("ProcessGetBlocks:", e.Error(), c.addr.Ip())
		return
	}
	cnt, e := btc.ReadVLen(b)
	if e != nil {
		println("ProcessGetBlocks:", e.Error(), c.addr.Ip())
		return
	}
	h2get := make([]*btc.Uint256, cnt)
	var h [32]byte
	for i := 0; i < int(cnt); i++ {
		n, _ := b.Read(h[:])
		if n != 32 {
			println("getblocks too short", c.addr.Ip())
			return
		}
		h2get[i] = btc.NewUint256(h[:])
		if dbg > 1 {
			println(c.addr.Ip(), "getbl", h2get[i].String())
		}
	}
	n, _ := b.Read(h[:])
	if n != 32 {
		println("getblocks does not have hash_stop", c.addr.Ip())
		return
	}
	hashstop := btc.NewUint256(h[:])

	var maxheight uint32
	invs := make(map[[32]byte]bool, 500)
	for i := range h2get {
		BlockChain.BlockIndexAccess.Lock()
		if bl, ok := BlockChain.BlockIndex[h2get[i].BIdx()]; ok {
			if bl.Height > maxheight {
				maxheight = bl.Height
			}
			addInvBlockBranch(invs, bl, hashstop)
		}
		BlockChain.BlockIndexAccess.Unlock()
		if len(invs) >= 500 {
			break
		}
	}
	inv := new(bytes.Buffer)
	btc.WriteVlen(inv, uint32(len(invs)))
	for k, _ := range invs {
		binary.Write(inv, binary.LittleEndian, uint32(2))
		inv.Write(k[:])
	}
	if dbg > 1 {
		fmt.Println(c.addr.Ip(), "getblocks", cnt, maxheight, " ...", len(invs), "invs in resp ->", len(inv.Bytes()))
	}
	InvsSent++
	c.SendRawMsg("inv", inv.Bytes())
}
예제 #2
0
파일: txaddsig.go 프로젝트: vipwzw/gocoin
func main() {
	if len(os.Args) != 5 {
		fmt.Println("This tool needs to be executed with 4 arguments:")
		fmt.Println(" 1) Name of the unsigned transaction file")
		fmt.Println(" 2) Input index to add the key & signature to")
		fmt.Println(" 3) Hex dump of the canonical signature")
		fmt.Println(" 4) Hex dump of the public key")
		return
	}
	tx := raw_tx_from_file(os.Args[1])
	if tx == nil {
		return
	}

	in, er := strconv.ParseUint(os.Args[2], 10, 32)
	if er != nil {
		println("Input index:", er.Error())
		return
	}

	if int(in) >= len(tx.TxIn) {
		println("Input index too big:", int(in), "/", len(tx.TxIn))
		return
	}

	sig, er := hex.DecodeString(os.Args[3])
	if er != nil {
		println("Signature:", er.Error())
		return
	}

	pk, er := hex.DecodeString(os.Args[4])
	if er != nil {
		println("Public key:", er.Error())
		return
	}

	buf := new(bytes.Buffer)
	btc.WriteVlen(buf, uint32(len(sig)))
	buf.Write(sig)
	btc.WriteVlen(buf, uint32(len(pk)))
	buf.Write(pk)

	tx.TxIn[in].ScriptSig = buf.Bytes()

	write_tx_file(tx)
}
예제 #3
0
func (c *OneConnection) SendOwnAddr() {
	if ExternalAddrLen() > 0 {
		buf := new(bytes.Buffer)
		btc.WriteVlen(buf, 1)
		binary.Write(buf, binary.LittleEndian, uint32(time.Now().Unix()))
		buf.Write(BestExternalAddr())
		c.SendRawMsg("addr", buf.Bytes())
	}
}
예제 #4
0
파일: net.go 프로젝트: spartacusX/gocoin
func (c *oneConnection) SendInvs(i2s []*[36]byte) {
	b := new(bytes.Buffer)
	btc.WriteVlen(b, uint32(len(i2s)))
	for i := range i2s {
		b.Write((*i2s[i])[:])
	}
	//println("sending invs", len(i2s), len(b.Bytes()))
	c.SendRawMsg("inv", b.Bytes())
}
예제 #5
0
func (c *OneConnection) SendAddr() {
	pers := GetBestPeers(MaxAddrsPerMessage, false)
	if len(pers) > 0 {
		buf := new(bytes.Buffer)
		btc.WriteVlen(buf, uint32(len(pers)))
		for i := range pers {
			binary.Write(buf, binary.LittleEndian, pers[i].Time)
			buf.Write(pers[i].NetAddr.Bytes())
		}
		c.SendRawMsg("addr", buf.Bytes())
	}
}
예제 #6
0
파일: invs.go 프로젝트: raszzh/gocoin
func (c *OneConnection) GetBlocks(pl []byte) {
	h2get, hashstop, e := parseLocatorsPayload(pl)

	if e != nil || len(h2get) < 1 || hashstop == nil {
		println("GetBlocks: error parsing payload from", c.PeerAddr.Ip())
		common.CountSafe("GetBlksBadPayload")
		c.DoS()
		return
	}

	invs := make(map[[32]byte]bool, 500)
	for i := range h2get {
		common.BlockChain.BlockIndexAccess.Lock()
		if bl, ok := common.BlockChain.BlockIndex[h2get[i].BIdx()]; ok {
			// make sure that this block is in our main chain
			common.Last.Mutex.Lock()
			end := common.Last.Block
			common.Last.Mutex.Unlock()
			for ; end != nil && end.Height >= bl.Height; end = end.Parent {
				if end == bl {
					addInvBlockBranch(invs, bl, hashstop) // Yes - this is the main chain
					if common.DebugLevel > 0 {
						fmt.Println(c.PeerAddr.Ip(), "getblocks from", bl.Height,
							"stop at", hashstop.String(), "->", len(invs), "invs")
					}

					if len(invs) > 0 {
						common.BlockChain.BlockIndexAccess.Unlock()

						inv := new(bytes.Buffer)
						btc.WriteVlen(inv, uint32(len(invs)))
						for k, _ := range invs {
							binary.Write(inv, binary.LittleEndian, uint32(2))
							inv.Write(k[:])
						}
						c.SendRawMsg("inv", inv.Bytes())
						return
					}
				}
			}
		}
		common.BlockChain.BlockIndexAccess.Unlock()
	}

	common.CountSafe("GetblksMissed")
	return
}
예제 #7
0
파일: data.go 프로젝트: raszzh/gocoin
// Handle getheaders protocol command
// https://en.bitcoin.it/wiki/Protocol_specification#getheaders
func (c *OneConnection) GetHeaders(pl []byte) {
	h2get, hashstop, e := parseLocatorsPayload(pl)
	if e != nil || hashstop == nil {
		println("GetHeaders: error parsing payload from", c.PeerAddr.Ip())
		common.CountSafe("GetHdrsBadPayload")
		c.DoS()
		return
	}

	if common.DebugLevel > 1 {
		println("GetHeaders", len(h2get), hashstop.String())
	}

	var best_block, last_block *btc.BlockTreeNode

	common.BlockChain.BlockIndexAccess.Lock()
	if len(h2get) > 0 {
		for i := range h2get {
			if bl, ok := common.BlockChain.BlockIndex[h2get[i].BIdx()]; ok {
				if best_block == nil || bl.Height > best_block.Height {
					best_block = bl
				}
			}
		}
	} else {
		best_block = common.BlockChain.BlockIndex[hashstop.BIdx()]
	}
	last_block = common.BlockChain.BlockTreeEnd
	common.BlockChain.BlockIndexAccess.Unlock()

	var resp []byte
	var cnt uint32
	for cnt < 2000 {
		best_block = best_block.FindPathTo(last_block)
		if best_block == nil {
			break
		}
		resp = append(resp, append(best_block.BlockHeader[:], 0)...) // 81st byte is always zero
		cnt++
	}

	out := new(bytes.Buffer)
	btc.WriteVlen(out, cnt)
	out.Write(resp)
	c.SendRawMsg("headers", out.Bytes())
	return
}
예제 #8
0
파일: invs.go 프로젝트: raszzh/gocoin
func (c *OneConnection) SendInvs() (res bool) {
	b := new(bytes.Buffer)
	c.Mutex.Lock()
	if len(c.PendingInvs) > 0 {
		btc.WriteVlen(b, uint32(len(c.PendingInvs)))
		for i := range c.PendingInvs {
			b.Write((*c.PendingInvs[i])[:])
		}
		res = true
	}
	c.PendingInvs = nil
	c.Mutex.Unlock()
	if res {
		c.SendRawMsg("inv", b.Bytes())
	}
	return
}
예제 #9
0
파일: invs.go 프로젝트: raszzh/gocoin
func (c *OneConnection) ProcessInv(pl []byte) {
	if len(pl) < 37 {
		println(c.PeerAddr.Ip(), "inv payload too short", len(pl))
		return
	}
	c.InvsRecieved++

	cnt, of := btc.VLen(pl)
	if len(pl) != of+36*cnt {
		println("inv payload length mismatch", len(pl), of, cnt)
	}

	var blinv2ask []byte

	for i := 0; i < cnt; i++ {
		typ := binary.LittleEndian.Uint32(pl[of : of+4])
		common.CountSafe(fmt.Sprint("InvGot", typ))
		if typ == 2 {
			if blockWanted(pl[of+4 : of+36]) {
				blinv2ask = append(blinv2ask, pl[of+4:of+36]...)
			}
		} else if typ == 1 {
			if common.CFG.TXPool.Enabled {
				c.TxInvNotify(pl[of+4 : of+36])
			}
		}
		of += 36
	}

	if len(blinv2ask) > 0 {
		bu := new(bytes.Buffer)
		btc.WriteVlen(bu, uint32(len(blinv2ask)/32))
		for i := 0; i < len(blinv2ask); i += 32 {
			bh := btc.NewUint256(blinv2ask[i : i+32])
			c.Mutex.Lock()
			c.GetBlockInProgress[bh.BIdx()] = &oneBlockDl{hash: bh, start: time.Now()}
			c.Mutex.Unlock()
			binary.Write(bu, binary.LittleEndian, uint32(2))
			bu.Write(bh.Hash[:])
		}
		c.SendRawMsg("getdata", bu.Bytes())
	}

	return
}
예제 #10
0
파일: ping.go 프로젝트: Bitoy/gocoin
func (c *one_net_conn) ping_idle() {
	c.ping.Lock()
	if c.ping.inProgress {
		if time.Now().After(c.ping.timeSent.Add(PING_TIMEOUT)) {
			c.store_ping_result()
			c.ping.Unlock()
			//fmt.Println(c.peerip, "ping timeout", c.ping.seq)
		} else {
			c.ping.Unlock()
			time.Sleep(time.Millisecond)
		}
	} else if c.ping.now {
		//fmt.Println("ping", c.peerip, c.ping.seq)
		c.ping.inProgress = true
		c.ping.timeSent = time.Now()
		c.ping.now = false
		if false {
			rand.Read(c.ping.pattern[:])
			c.ping.Unlock()
			c.sendmsg("ping", c.ping.pattern[:])
		} else {
			b := new(bytes.Buffer)
			btc.WriteVlen(b, PING_FETCH_BLOCKS)
			BlocksMutex.Lock()
			for i := uint32(1); ; i++ {
				binary.Write(b, binary.LittleEndian, uint32(2))
				btg := BlocksToGet[i]
				b.Write(btg[:])
				if i == PING_FETCH_BLOCKS {
					c.ping.lastBlock = btc.NewUint256(btg[:])
					break
				}
			}
			BlocksMutex.Unlock()
			c.ping.bytes = 0
			c.ping.Unlock()
			c.sendmsg("getdata", b.Bytes())
			//fmt.Println("ping sent", c.ping.lastBlock.String())
		}
	} else {
		c.ping.Unlock()
		time.Sleep(10 * time.Millisecond)
	}
}
예제 #11
0
파일: blks.go 프로젝트: vipwzw/gocoin
func (c *one_net_conn) getnextblock() {
	var cnt, lensofar int
	b := new(bytes.Buffer)
	vl := new(bytes.Buffer)

	BlocksMutex.Lock()

	if BlocksComplete > BlocksIndex {
		fmt.Println("dupa", BlocksComplete, BlocksIndex)
		BlocksIndex = BlocksComplete
	}

	blocks_from := BlocksIndex

	avg_len := avg_block_size()
	max_block_forward := uint32((MemForBlocks - BlocksCachedSize) / uint(avg_len))
	if max_block_forward < MIN_BLOCKS_AHEAD {
		max_block_forward = MIN_BLOCKS_AHEAD
	} else if max_block_forward > MAX_BLOCKS_AHEAD {
		max_block_forward = MAX_BLOCKS_AHEAD
	}

	if BlocksComplete+max_block_forward < blocks_from {
		COUNTER("BGAP")
		max_block_forward = blocks_from - BlocksComplete + 1
	}

	var prot int
	for secondloop := false; cnt < 10e3 && lensofar < GETBLOCKS_BYTES_ONCE; secondloop = true {
		if prot == 20e3 {
			println("stuck in getnextblock()", BlocksIndex, blocks_from, max_block_forward,
				BlocksComplete, LastBlockHeight, _DoBlocks, secondloop)
			break
		}
		prot++

		if secondloop && BlocksIndex == blocks_from {
			if BlocksComplete == LastBlockHeight {
				_DoBlocks = false
			} else {
				COUNTER("WRAP")
				time.Sleep(1e8)
			}
			break
		}

		BlocksIndex++
		if BlocksIndex > BlocksComplete+max_block_forward || BlocksIndex > LastBlockHeight {
			//fmt.Println("wrap", BlocksIndex, BlocksComplete)
			BlocksIndex = BlocksComplete
		}

		if _, done := BlocksCached[BlocksIndex]; done {
			//fmt.Println(" cached ->", BlocksIndex)
			continue
		}

		bh, ok := BlocksToGet[BlocksIndex]
		if !ok {
			//fmt.Println(" toget ->", BlocksIndex)
			continue
		}

		cbip := BlocksInProgress[bh]
		if cbip == nil {
			cbip = &one_bip{Height: BlocksIndex, Count: 1}
			cbip.Conns = make(map[uint32]bool, MaxNetworkConns)
		} else {
			if cbip.Conns[c.id] {
				//fmt.Println(" cbip.Conns ->", c.id)
				continue
			}
			cbip.Count++
		}
		cbip.Conns[c.id] = true
		c.inprogress++
		BlocksInProgress[bh] = cbip

		b.Write([]byte{2, 0, 0, 0})
		b.Write(bh[:])
		cnt++
		lensofar += avg_len
	}
	BlocksMutex.Unlock()

	btc.WriteVlen(vl, uint32(cnt))

	c.sendmsg("getdata", append(vl.Bytes(), b.Bytes()...))
	c.last_blk_rcvd = time.Now()
}
예제 #12
0
파일: invs.go 프로젝트: 22140505/gocoin
func (c *OneConnection) ProcessGetBlocks(pl []byte) {
	b := bytes.NewReader(pl)
	var ver uint32
	e := binary.Read(b, binary.LittleEndian, &ver)
	if e != nil {
		println("ProcessGetBlocks:", e.Error(), c.PeerAddr.Ip())
		common.CountSafe("GetblksNoVer")
		c.DoS()
		return
	}
	cnt, e := btc.ReadVLen(b)
	if e != nil {
		println("ProcessGetBlocks:", e.Error(), c.PeerAddr.Ip())
		common.CountSafe("GetblksNoVlen")
		c.DoS()
		return
	}

	if cnt < 1 {
		println("ProcessGetBlocks: empty inv list", c.PeerAddr.Ip())
		common.CountSafe("GetblksNoInvs")
		c.DoS()
		return
	}

	h2get := make([]*btc.Uint256, cnt)
	var h [32]byte
	for i := 0; i < int(cnt); i++ {
		n, _ := b.Read(h[:])
		if n != 32 {
			if common.DebugLevel > 0 {
				println("getblocks too short", c.PeerAddr.Ip())
			}
			common.CountSafe("GetblksTooShort")
			c.DoS()
			return
		}
		h2get[i] = btc.NewUint256(h[:])
		if common.DebugLevel > 2 {
			println(c.PeerAddr.Ip(), "getbl", h2get[i].String())
		}
	}
	n, _ := b.Read(h[:])
	if n != 32 {
		if common.DebugLevel > 0 {
			println("getblocks does not have hash_stop", c.PeerAddr.Ip())
		}
		common.CountSafe("GetblksNoStop")
		c.DoS()
		return
	}
	hashstop := btc.NewUint256(h[:])

	invs := make(map[[32]byte]bool, 500)
	for i := range h2get {
		common.BlockChain.BlockIndexAccess.Lock()
		if bl, ok := common.BlockChain.BlockIndex[h2get[i].BIdx()]; ok {
			// make sure that this block is in our main chain
			common.Last.Mutex.Lock()
			end := common.Last.Block
			common.Last.Mutex.Unlock()
			for ; end != nil && end.Height >= bl.Height; end = end.Parent {
				if end == bl {
					addInvBlockBranch(invs, bl, hashstop) // Yes - this is the main chain
					if common.DebugLevel > 0 {
						fmt.Println(c.PeerAddr.Ip(), "getblocks from", bl.Height,
							"stop at", hashstop.String(), "->", len(invs), "invs")
					}

					if len(invs) > 0 {
						common.BlockChain.BlockIndexAccess.Unlock()

						inv := new(bytes.Buffer)
						btc.WriteVlen(inv, uint32(len(invs)))
						for k, _ := range invs {
							binary.Write(inv, binary.LittleEndian, uint32(2))
							inv.Write(k[:])
						}
						c.SendRawMsg("inv", inv.Bytes())
						return
					}
				}
			}
		}
		common.BlockChain.BlockIndexAccess.Unlock()
	}

	common.CountSafe("GetblksMissed")
	return
}
예제 #13
0
파일: data.go 프로젝트: raszzh/gocoin
func (c *OneConnection) ProcessGetData(pl []byte) {
	var notfound []byte

	//println(c.PeerAddr.Ip(), "getdata")
	b := bytes.NewReader(pl)
	cnt, e := btc.ReadVLen(b)
	if e != nil {
		println("ProcessGetData:", e.Error(), c.PeerAddr.Ip())
		return
	}
	for i := 0; i < int(cnt); i++ {
		var typ uint32
		var h [36]byte

		n, _ := b.Read(h[:])
		if n != 36 {
			println("ProcessGetData: pl too short", c.PeerAddr.Ip())
			return
		}

		typ = binary.LittleEndian.Uint32(h[:4])

		common.CountSafe(fmt.Sprint("GetdataType", typ))
		if typ == 2 {
			uh := btc.NewUint256(h[4:])
			bl, _, er := common.BlockChain.Blocks.BlockGet(uh)
			if er == nil {
				c.SendRawMsg("block", bl)
			} else {
				notfound = append(notfound, h[:]...)
			}
		} else if typ == 1 {
			// transaction
			uh := btc.NewUint256(h[4:])
			TxMutex.Lock()
			if tx, ok := TransactionsToSend[uh.Hash]; ok && tx.Blocked == 0 {
				tx.SentCnt++
				tx.Lastsent = time.Now()
				TxMutex.Unlock()
				c.SendRawMsg("tx", tx.Data)
			} else {
				TxMutex.Unlock()
				notfound = append(notfound, h[:]...)
			}
		} else {
			if common.DebugLevel > 0 {
				println("getdata for type", typ, "not supported yet")
			}
			if typ > 0 && typ <= 3 /*3 is a filtered block(we dont support it)*/ {
				notfound = append(notfound, h[:]...)
			}
		}
	}

	if len(notfound) > 0 {
		buf := new(bytes.Buffer)
		btc.WriteVlen(buf, uint32(len(notfound)/36))
		buf.Write(notfound)
		c.SendRawMsg("notfound", buf.Bytes())
	}
}