コード例 #1
0
ファイル: cblk.go プロジェクト: piotrnar/gocoin
func (c *OneConnection) ProcessGetBlockTxn(pl []byte) {
	if len(pl) < 34 {
		println(c.ConnID, "GetBlockTxnShort")
		c.DoS("GetBlockTxnShort")
		return
	}
	hash := btc.NewUint256(pl[:32])
	crec := GetchBlockForBIP152(hash)
	if crec == nil {
		fmt.Println(c.ConnID, "GetBlockTxn aborting for", hash.String())
		return
	}

	req := bytes.NewReader(pl[32:])
	indexes_length, _ := btc.ReadVLen(req)
	if indexes_length == 0 {
		println(c.ConnID, "GetBlockTxnEmpty")
		c.DoS("GetBlockTxnEmpty")
		return
	}

	var exp_idx uint64
	msg := new(bytes.Buffer)

	msg.Write(hash.Hash[:])
	btc.WriteVlen(msg, indexes_length)

	for {
		idx, er := btc.ReadVLen(req)
		if er != nil {
			println(c.ConnID, "GetBlockTxnERR")
			c.DoS("GetBlockTxnERR")
			return
		}
		idx += exp_idx
		if int(idx) >= len(crec.Block.Txs) {
			println(c.ConnID, "GetBlockTxnIdx+")
			c.DoS("GetBlockTxnIdx+")
			return
		}
		if c.Node.SendCmpctVer == 2 {
			msg.Write(crec.Block.Txs[idx].Raw) // coinbase - index 0
		} else {
			crec.Block.Txs[idx].WriteSerialized(msg) // coinbase - index 0
		}
		if indexes_length == 1 {
			break
		}
		indexes_length--
		exp_idx = idx + 1
	}

	c.SendRawMsg("blocktxn", msg.Bytes())
}
コード例 #2
0
ファイル: hdrs.go プロジェクト: vancsj/gocoin
func (c *one_net_conn) headers(d []byte) {
	var hdr [81]byte
	b := bytes.NewReader(d)
	cnt, er := btc.ReadVLen(b)
	if er != nil {
		return
	}
	if cnt == 0 /*|| LastBlock.node.Height>=10e3*/ {
		SetAllHeadersDone(true)
		return
	}
	for i := uint64(0); i < cnt; i++ {
		if _, er = b.Read(hdr[:]); er != nil {
			return
		}
		if hdr[80] != 0 {
			fmt.Println(LastBlock.node.Height, "Unexpected value of txn_count")
			continue
		}
		bl, er := btc.NewBlock(hdr[:])
		if er == nil {
			er = chkblock(bl)
			if er != nil {
				fmt.Println(er.Error())
				os.Exit(1)
			}
		} else {
			fmt.Println(LastBlock.node.Height, er.Error())
		}
	}
	//fmt.Println("Height:", LastBlock.node.Height)
}
コード例 #3
0
ファイル: addr.go プロジェクト: rollyleal/gocoin
// Parese network's "addr" message
func (c *OneConnection) ParseAddr(pl []byte) {
	b := bytes.NewBuffer(pl)
	cnt, _ := btc.ReadVLen(b)
	for i := 0; i < int(cnt); i++ {
		var buf [30]byte
		n, e := b.Read(buf[:])
		if n != len(buf) || e != nil {
			common.CountSafe("AddrError")
			c.DoS("AddrError")
			//println("ParseAddr:", n, e)
			break
		}
		a := peersdb.NewPeer(buf[:])
		if !sys.ValidIp4(a.Ip4[:]) {
			c.Misbehave("AddrLocal", 2)
		} else if time.Unix(int64(a.Time), 0).Before(time.Now().Add(time.Minute)) {
			if time.Now().Before(time.Unix(int64(a.Time), 0).Add(peersdb.ExpirePeerAfter)) {
				k := qdb.KeyType(a.UniqID())
				v := peersdb.PeerDB.Get(k)
				if v != nil {
					a.Banned = peersdb.NewPeer(v[:]).Banned
				}
				peersdb.PeerDB.Put(k, a.Bytes())
			} else {
				common.CountSafe("AddrStale")
			}
		} else {
			c.Misbehave("AddrFuture", 5)
		}
	}
}
コード例 #4
0
ファイル: addr.go プロジェクト: liudch/gocoin
func parse_addr(pl []byte) {
	b := bytes.NewBuffer(pl)
	cnt, _ := btc.ReadVLen(b)
	for i := 0; i < int(cnt); i++ {
		var buf [30]byte
		n, e := b.Read(buf[:])
		if n != len(buf) || e != nil {
			COUNTER("ADER")
			break
		}
		a := peersdb.NewPeer(buf[:])
		if !sys.ValidIp4(a.Ip4[:]) {
			COUNTER("ADNO")
		} else if time.Unix(int64(a.Time), 0).Before(time.Now().Add(time.Minute)) {
			if time.Now().Before(time.Unix(int64(a.Time), 0).Add(peersdb.ExpirePeerAfter)) {
				k := qdb.KeyType(a.UniqID())
				v := peersdb.PeerDB.Get(k)
				if v != nil {
					a.Banned = peersdb.NewPeer(v[:]).Banned
				}
				peersdb.PeerDB.Put(k, a.Bytes())
			} else {
				COUNTER("ADST")
			}
		} else {
			COUNTER("ADFU")
		}
	}
}
コード例 #5
0
ファイル: addr.go プロジェクト: vancsj/gocoin
func parse_addr(pl []byte) {
	b := bytes.NewBuffer(pl)
	cnt, _ := btc.ReadVLen(b)
	for i := 0; i < int(cnt); i++ {
		var buf [30]byte
		var ip4 [4]byte
		n, e := b.Read(buf[:])
		if n != len(buf) || e != nil {
			fmt.Println("parse_addr:", n, e)
			break
		}
		copy(ip4[:], buf[24:28])
		if validip4(ip4[:]) {
			AddrMutex.Lock()
			if _, pres := AddrDatbase[ip4]; !pres {
				AddrDatbase[ip4] = false
			}
			AddrMutex.Unlock()
		}
	}
}
コード例 #6
0
ファイル: addr.go プロジェクト: piotrnar/gocoin
// Parese network's "addr" message
func (c *OneConnection) ParseAddr(pl []byte) {
	b := bytes.NewBuffer(pl)
	cnt, _ := btc.ReadVLen(b)
	for i := 0; i < int(cnt); i++ {
		var buf [30]byte
		n, e := b.Read(buf[:])
		if n != len(buf) || e != nil {
			common.CountSafe("AddrError")
			c.DoS("AddrError")
			//println("ParseAddr:", n, e)
			break
		}
		a := peersdb.NewPeer(buf[:])
		if !sys.ValidIp4(a.Ip4[:]) {
			//common.CountSafe("AddrLocal")
			if c.Misbehave("AddrLocal", 1) {
				break
			}
			//print(c.PeerAddr.Ip(), " ", c.Node.Agent, " ", c.Node.Version, " addr local ", a.String(), "\n> ")
		} else if time.Unix(int64(a.Time), 0).Before(time.Now().Add(time.Minute)) {
			if time.Now().Before(time.Unix(int64(a.Time), 0).Add(peersdb.ExpirePeerAfter)) {
				k := qdb.KeyType(a.UniqID())
				v := peersdb.PeerDB.Get(k)
				if v != nil {
					a.Banned = peersdb.NewPeer(v[:]).Banned
				}
				a.Time = uint32(time.Now().Add(-5 * time.Minute).Unix()) // add new peers as not just alive
				peersdb.PeerDB.Put(k, a.Bytes())
			} else {
				common.CountSafe("AddrStale")
			}
		} else {
			if c.Misbehave("AddrFuture", 50) {
				break
			}
		}
	}
}
コード例 #7
0
ファイル: data.go プロジェクト: vancsj/gocoin
// Read VLen followed by the number of locators
// parse the payload of getblocks and getheaders messages
func parseLocatorsPayload(pl []byte) (h2get []*btc.Uint256, hashstop *btc.Uint256, er error) {
	var cnt uint64
	var h [32]byte
	var ver uint32

	b := bytes.NewReader(pl)

	// version
	if er = binary.Read(b, binary.LittleEndian, &ver); er != nil {
		return
	}

	// hash count
	cnt, er = btc.ReadVLen(b)
	if er != nil {
		return
	}

	// block locator hashes
	if cnt > 0 {
		h2get = make([]*btc.Uint256, cnt)
		for i := 0; i < int(cnt); i++ {
			if _, er = b.Read(h[:]); er != nil {
				return
			}
			h2get[i] = btc.NewUint256(h[:])
		}
	}

	// hash_stop
	if _, er = b.Read(h[:]); er != nil {
		return
	}
	hashstop = btc.NewUint256(h[:])

	return
}
コード例 #8
0
ファイル: hdrs.go プロジェクト: piotrnar/gocoin
func (c *OneConnection) HandleHeaders(pl []byte) (new_headers_got int) {
	var highest_block_found uint32

	c.X.GetHeadersInProgress = false

	b := bytes.NewReader(pl)
	cnt, e := btc.ReadVLen(b)
	if e != nil {
		println("HandleHeaders:", e.Error(), c.PeerAddr.Ip())
		return
	}

	if cnt > 0 {
		MutexRcv.Lock()
		defer MutexRcv.Unlock()

		for i := 0; i < int(cnt); i++ {
			var hdr [81]byte

			n, _ := b.Read(hdr[:])
			if n != 81 {
				println("HandleHeaders: pl too short", c.PeerAddr.Ip())
				c.DoS("HdrErr1")
				return
			}

			if hdr[80] != 0 {
				fmt.Println("Unexpected value of txn_count from", c.PeerAddr.Ip())
				c.DoS("HdrErr2")
				return
			}

			sta, b2g := c.ProcessNewHeader(hdr[:])
			if b2g == nil {
				if sta == PH_STATUS_FATAL {
					//println("c.DoS(BadHeader)")
					c.DoS("BadHeader")
					return
				} else if sta == PH_STATUS_ERROR {
					//println("c.Misbehave(BadHeader)")
					c.Misbehave("BadHeader", 50) // do it 20 times and you are banned
				}
			} else {
				if sta == PH_STATUS_NEW {
					new_headers_got++
				}
				if b2g.Block.Height > highest_block_found {
					highest_block_found = b2g.Block.Height
				}
				if c.Node.Height < b2g.Block.Height {
					c.Node.Height = b2g.Block.Height
				}
				c.X.GetBlocksDataNow = true
				b2g.TmPreproc = time.Now()
			}
		}
	}

	c.Mutex.Lock()
	c.X.LastHeadersEmpty = highest_block_found <= c.X.LastHeadersHeightAsk
	c.X.TotalNewHeadersCount += new_headers_got
	if new_headers_got == 0 {
		c.X.AllHeadersReceived = true
	}
	c.Mutex.Unlock()

	return
}
コード例 #9
0
ファイル: data.go プロジェクト: vancsj/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.BIdx()]; 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())
	}
}
コード例 #10
0
ファイル: data.go プロジェクト: piotrnar/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])
		c.Mutex.Lock()
		c.InvStore(typ, h[4:36])
		c.Mutex.Unlock()

		common.CountSafe(fmt.Sprintf("GetdataType-%x", typ))
		if typ == MSG_BLOCK || typ == MSG_WITNESS_BLOCK {
			crec, _, er := common.BlockChain.Blocks.BlockGetExt(btc.NewUint256(h[4:]))
			//bl, _, er := common.BlockChain.Blocks.BlockGet(btc.NewUint256(h[4:]))
			if er == nil {
				bl := crec.Data
				if typ == MSG_BLOCK {
					// remove witness data from the block
					if crec.Block == nil {
						crec.Block, _ = btc.NewBlock(bl)
					}
					if crec.Block.OldData == nil {
						crec.Block.BuildTxList()
					}
					//println("block size", len(crec.Data), "->", len(bl))
					bl = crec.Block.OldData
				}
				c.SendRawMsg("block", bl)
			} else {
				notfound = append(notfound, h[:]...)
			}
		} else if typ == MSG_TX || typ == MSG_WITNESS_TX {
			// transaction
			TxMutex.Lock()
			if tx, ok := TransactionsToSend[btc.NewUint256(h[4:]).BIdx()]; ok && tx.Blocked == 0 {
				tx.SentCnt++
				tx.Lastsent = time.Now()
				TxMutex.Unlock()
				if tx.SegWit == nil || typ == MSG_WITNESS_TX {
					c.SendRawMsg("tx", tx.Data)
				} else {
					c.SendRawMsg("tx", tx.Serialize())
				}
			} else {
				TxMutex.Unlock()
				notfound = append(notfound, h[:]...)
			}
		} else if typ == MSG_CMPCT_BLOCK {
			c.SendCmpctBlk(btc.NewUint256(h[4:]))
		} 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, uint64(len(notfound)/36))
		buf.Write(notfound)
		c.SendRawMsg("notfound", buf.Bytes())
	}
}