Пример #1
0
func retry_cached_blocks() bool {
	if len(network.CachedBlocks) == 0 {
		return false
	}
	accepted_cnt := 0
	for k, v := range network.CachedBlocks {
		common.Busy("Cache.CheckBlock " + v.Block.Hash.String())
		e, dos, maybelater := common.BlockChain.CheckBlock(v.Block)
		if e == nil {
			common.Busy("Cache.AcceptBlock " + v.Block.Hash.String())
			e := LocalAcceptBlock(v.Block, v.Conn)
			if e == nil {
				//fmt.Println("*** Old block accepted", common.BlockChain.BlockTreeEnd.Height)
				common.CountSafe("BlocksFromCache")
				delete(network.CachedBlocks, k)
				accepted_cnt++
				break // One at a time should be enough
			} else {
				fmt.Println("retry AcceptBlock:", e.Error())
				v.Conn.DoS("BadCachedBlock1")
				delete(network.CachedBlocks, k)
			}
		} else {
			if !maybelater {
				fmt.Println("retry CheckBlock:", e.Error())
				common.CountSafe("BadCachedBlocks")
				if dos {
					v.Conn.DoS("BadCachedBlock2")
				}
				delete(network.CachedBlocks, k)
			}
		}
	}
	return accepted_cnt > 0 && len(network.CachedBlocks) > 0
}
Пример #2
0
// 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)
		}
	}
}
Пример #3
0
// This function is called from a net conn thread
func netBlockReceived(conn *OneConnection, b []byte) {
	bl, e := btc.NewBlock(b)
	if e != nil {
		conn.DoS("BrokenBlock")
		println("NewBlock:", e.Error())
		return
	}

	idx := bl.Hash.BIdx()
	MutexRcv.Lock()
	if rb, got := ReceivedBlocks[idx]; got {
		rb.Cnt++
		MutexRcv.Unlock()
		common.CountSafe("BlockSameRcvd")
		return
	}
	orb := &OneReceivedBlock{Time: time.Now()}
	if bip, ok := conn.GetBlockInProgress[idx]; ok {
		orb.TmDownload = orb.Time.Sub(bip.start)
		conn.Mutex.Lock()
		delete(conn.GetBlockInProgress, idx)
		conn.Mutex.Unlock()
	} else {
		common.CountSafe("UnxpectedBlockRcvd")
	}
	ReceivedBlocks[idx] = orb
	MutexRcv.Unlock()

	NetBlocks <- &BlockRcvd{Conn: conn, Block: bl}
}
Пример #4
0
// Handle incoming "tx" msg
func (c *OneConnection) ParseTxNet(pl []byte) {
	if uint32(len(pl)) > atomic.LoadUint32(&common.CFG.TXPool.MaxTxSize) {
		common.CountSafe("TxRejectedBig")
		return
	}
	tx, le := btc.NewTx(pl)
	if tx == nil {
		c.DoS("TxRejectedBroken")
		return
	}
	if le != len(pl) {
		c.DoS("TxRejectedLenMismatch")
		return
	}
	if len(tx.TxIn) < 1 {
		c.Misbehave("TxRejectedNoInputs", 100)
		return
	}

	tx.SetHash(pl)
	NeedThisTx(tx.Hash, func() {
		// This body is called with a locked TxMutex
		tx.Raw = pl
		select {
		case NetTxs <- &TxRcvd{conn: c, tx: tx, raw: pl}:
			TransactionsPending[tx.Hash.BIdx()] = true
		default:
			common.CountSafe("TxRejectedFullQ")
			//println("NetTxsFULL")
		}
	})
}
Пример #5
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")
		}
	})
}
Пример #6
0
// This function is called from the main thread (or from an UI)
func NetRouteInv(typ uint32, h *btc.Uint256, fromConn *OneConnection) (cnt uint) {
	common.CountSafe(fmt.Sprint("NetRouteInv", typ))

	// Prepare the inv
	inv := new([36]byte)
	binary.LittleEndian.PutUint32(inv[0:4], typ)
	copy(inv[4:36], h.Bytes())

	// Append it to PendingInvs in each open connection
	Mutex_net.Lock()
	for _, v := range OpenCons {
		if v != fromConn { // except the one that this inv came from
			v.Mutex.Lock()
			if v.Node.DoNotRelayTxs && typ == 1 {
				// This node does not want tx inv (it came with its version message)
				common.CountSafe("SendInvNoTxNode")
			} else {
				if fromConn == nil && v.InvsRecieved == 0 {
					// Do not broadcast own txs to nodes that never sent any invs to us
					common.CountSafe("SendInvOwnBlocked")
				} else if len(v.PendingInvs) < 500 {
					v.PendingInvs = append(v.PendingInvs, inv)
					cnt++
				} else {
					common.CountSafe("SendInvIgnored")
				}
			}
			v.Mutex.Unlock()
		}
	}
	Mutex_net.Unlock()
	return
}
Пример #7
0
func ExpirePeers() {
	peerdb_mutex.Lock()
	var delcnt uint32
	now := time.Now()
	todel := make([]qdb.KeyType, PeerDB.Count())
	PeerDB.Browse(func(k qdb.KeyType, v []byte) uint32 {
		ptim := binary.LittleEndian.Uint32(v[0:4])
		if now.After(time.Unix(int64(ptim), 0).Add(ExpirePeerAfter)) {
			todel[delcnt] = k // we cannot call Del() from here
			delcnt++
		}
		return 0
	})
	if delcnt > 0 {
		common.CountSafeAdd("PeersExpired", uint64(delcnt))
		for delcnt > 0 {
			delcnt--
			PeerDB.Del(todel[delcnt])
		}
		common.CountSafe("PeerDefragsDone")
		PeerDB.Defrag()
	} else {
		common.CountSafe("PeerDefragsNone")
	}
	peerdb_mutex.Unlock()
}
Пример #8
0
// Called from the blockchain thread
func HandleNetBlock(newbl *network.BlockRcvd) {
	if CheckParentDiscarded(newbl.BlockTreeNode) {
		common.CountSafe("DiscardFreshBlockA")
		retryCachedBlocks = len(network.CachedBlocks) > 0
		return
	}

	if !common.BlockChain.HasAllParents(newbl.BlockTreeNode) {
		// it's not linking - keep it for later
		network.CachedBlocks = append(network.CachedBlocks, newbl)
		common.CountSafe("BlockPostone")
		return
	}

	common.Busy("LocalAcceptBlock " + newbl.Hash.String())
	e := LocalAcceptBlock(newbl)
	if e != nil {
		common.CountSafe("DiscardFreshBlockB")
		fmt.Println("AcceptBlock:", e.Error())
		newbl.Conn.DoS("LocalAcceptBl")
	} else {
		//println("block", newbl.Block.Height, "accepted")
		retryCachedBlocks = retry_cached_blocks()
	}
}
Пример #9
0
// Parese network's "addr" message
func 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")
			//println("ParseAddr:", n, e)
			break
		}
		a := NewPeer(buf[:])
		if !ValidIp4(a.Ip4[:]) {
			common.CountSafe("AddrInvalid")
		} 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(ExpirePeerAfter)) {
				k := qdb.KeyType(a.UniqID())
				v := PeerDB.Get(k)
				if v != nil {
					a.Banned = NewPeer(v[:]).Banned
				}
				PeerDB.Put(k, a.Bytes())
			} else {
				common.CountSafe("AddrStale")
			}
		} else {
			common.CountSafe("AddrInFuture")
		}
	}
}
Пример #10
0
func retry_cached_blocks() bool {
	var idx int
	common.CountSafe("RedoCachedBlks")
	for idx < len(network.CachedBlocks) {
		newbl := network.CachedBlocks[idx]
		if CheckParentDiscarded(newbl.BlockTreeNode) {
			common.CountSafe("DiscardCachedBlock")
			network.CachedBlocks = append(network.CachedBlocks[:idx], network.CachedBlocks[idx+1:]...)
			return len(network.CachedBlocks) > 0
		}
		if common.BlockChain.HasAllParents(newbl.BlockTreeNode) {
			common.Busy("Cache.LocalAcceptBlock " + newbl.Block.Hash.String())
			e := LocalAcceptBlock(newbl)
			if e != nil {
				fmt.Println("AcceptBlock:", e.Error())
				newbl.Conn.DoS("LocalAcceptBl")
			}
			if usif.Exit_now {
				return false
			}
			// remove it from cache
			network.CachedBlocks = append(network.CachedBlocks[:idx], network.CachedBlocks[idx+1:]...)
			return len(network.CachedBlocks) > 0
		} else {
			idx++
		}
	}
	return false
}
Пример #11
0
func TxMined(h *btc.Uint256) {
	TxMutex.Lock()
	if rec, ok := TransactionsToSend[h.Hash]; ok {
		common.CountSafe("TxMinedToSend")
		for i := range rec.Spent {
			delete(SpentOutputs, rec.Spent[i])
		}
		delete(TransactionsToSend, h.Hash)
	}
	if _, ok := TransactionsRejected[h.BIdx()]; ok {
		common.CountSafe("TxMinedRejected")
		deleteRejected(h.BIdx())
	}
	if _, ok := TransactionsPending[h.Hash]; ok {
		common.CountSafe("TxMinedPending")
		delete(TransactionsPending, h.Hash)
	}
	wtg := WaitingForInputs[h.BIdx()]
	TxMutex.Unlock()

	// Try to redo waiting txs
	if wtg != nil {
		common.CountSafe("TxMinedGotInput")
		RetryWaitingForInput(wtg)
	}
}
Пример #12
0
func (c *OneConnection) Misbehave(why string, how_much int) {
	common.CountSafe("Bad" + why)
	c.Mutex.Lock()
	c.misbehave += how_much
	if c.misbehave >= 100 {
		common.CountSafe("BanMisbehave")
		c.banit = true
		c.broken = true
	}
	c.Mutex.Unlock()
}
Пример #13
0
func txChecker(h *btc.Uint256) bool {
	TxMutex.Lock()
	rec, ok := TransactionsToSend[h.BIdx()]
	TxMutex.Unlock()
	if ok && rec.Own != 0 {
		return false // Assume own txs as non-trusted
	}
	if ok {
		common.CountSafe("TxScrBoosted")
	} else {
		common.CountSafe("TxScrMissed")
	}
	return ok
}
Пример #14
0
// This function is called from the main thread (or from an UI)
func NetRouteInvExt(typ uint32, h *btc.Uint256, fromConn *OneConnection, fee_spkb uint64) (cnt uint) {
	common.CountSafe(fmt.Sprint("NetRouteInv", typ))

	// Prepare the inv
	inv := new([36]byte)
	binary.LittleEndian.PutUint32(inv[0:4], typ)
	copy(inv[4:36], h.Bytes())

	// Append it to PendingInvs in each open connection
	Mutex_net.Lock()
	for _, v := range OpenCons {
		if v != fromConn { // except the one that this inv came from
			send_inv := true
			v.Mutex.Lock()
			if typ == MSG_TX {
				if v.Node.DoNotRelayTxs {
					send_inv = false
					common.CountSafe("SendInvNoTxNode")
				} else if v.X.MinFeeSPKB > 0 && uint64(v.X.MinFeeSPKB) > fee_spkb {
					send_inv = false
					common.CountSafe("SendInvFeeTooLow")
				}

				/* This is to prevent sending own txs to "spying" peers:
				else if fromConn==nil && v.X.InvsRecieved==0 {
					send_inv = false
					common.CountSafe("SendInvOwnBlocked")
				}
				*/
			}
			if send_inv {
				if len(v.PendingInvs) < 500 {
					if typ, ok := v.InvDone.Map[hash2invid(inv[4:36])]; ok {
						common.CountSafe(fmt.Sprint("SendInvSame-", typ))
					} else {
						v.PendingInvs = append(v.PendingInvs, inv)
						cnt++
					}
				} else {
					common.CountSafe("SendInvFull")
				}
			}
			v.Mutex.Unlock()
		}
	}
	Mutex_net.Unlock()
	return
}
Пример #15
0
func (c *OneConnection) HandleVersion(pl []byte) error {
	if len(pl) >= 80 /*Up to, includiong, the nonce */ {
		c.Mutex.Lock()
		c.Node.Version = binary.LittleEndian.Uint32(pl[0:4])
		if bytes.Equal(pl[72:80], nonce[:]) {
			c.Mutex.Unlock()
			return errors.New("Connecting to ourselves")
		}
		if c.Node.Version < MIN_PROTO_VERSION {
			c.Mutex.Unlock()
			return errors.New("Client version too low")
		}
		c.Node.Services = binary.LittleEndian.Uint64(pl[4:12])
		c.Node.Timestamp = binary.LittleEndian.Uint64(pl[12:20])
		c.Node.ReportedIp4 = binary.BigEndian.Uint32(pl[40:44])
		if len(pl) >= 86 {
			le, of := btc.VLen(pl[80:])
			of += 80
			c.Node.Agent = string(pl[of : of+le])
			of += le
			if len(pl) >= of+4 {
				c.Node.Height = binary.LittleEndian.Uint32(pl[of : of+4])
				c.X.GetBlocksDataNow = true
				of += 4
				if len(pl) > of && pl[of] == 0 {
					c.Node.DoNotRelayTxs = true
				}
			}
		}
		c.Mutex.Unlock()

		if sys.ValidIp4(pl[40:44]) {
			ExternalIpMutex.Lock()
			_, use_this_ip := ExternalIp4[c.Node.ReportedIp4]
			if !use_this_ip { // New IP
				use_this_ip = true
				for x, v := range IgnoreExternalIpFrom {
					if c.Node.Agent == v {
						use_this_ip = false
						common.CountSafe(fmt.Sprint("IgnoreExtIP", x))
						break
					}
				}
				if use_this_ip {
					fmt.Printf("New external IP %d.%d.%d.%d from %s\n> ",
						pl[40], pl[41], pl[42], pl[43], c.Node.Agent)
				}
			}
			if use_this_ip {
				ExternalIp4[c.Node.ReportedIp4] = [2]uint{ExternalIp4[c.Node.ReportedIp4][0] + 1,
					uint(time.Now().Unix())}
			}
			ExternalIpMutex.Unlock()
		}
	} else {
		return errors.New("version message too short")
	}
	c.SendRawMsg("verack", []byte{})
	return nil
}
Пример #16
0
func (c *OneConnection) SendPendingData() bool {
	if c.SendBufProd != c.SendBufCons {
		bytes_to_send := c.SendBufProd - c.SendBufCons
		if bytes_to_send < 0 {
			bytes_to_send += SendBufSize
		}
		if c.SendBufCons+bytes_to_send > SendBufSize {
			bytes_to_send = SendBufSize - c.SendBufCons
		}

		n, e := common.SockWrite(c.Conn, c.sendBuf[c.SendBufCons:c.SendBufCons+bytes_to_send])
		if n > 0 {
			c.Mutex.Lock()
			c.X.LastSent = time.Now()
			c.X.BytesSent += uint64(n)
			n += c.SendBufCons
			if n >= SendBufSize {
				c.SendBufCons = 0
			} else {
				c.SendBufCons = n
			}
			c.Mutex.Unlock()
		} else if time.Now().After(c.X.LastSent.Add(AnySendTimeout)) {
			common.CountSafe("PeerSendTimeout")
			c.Disconnect()
		} else if e != nil {
			if common.DebugLevel > 0 {
				println(c.PeerAddr.Ip(), "Connection Broken during send")
			}
			c.Disconnect()
		}
	}
	return c.SendBufProd != c.SendBufCons
}
Пример #17
0
func (c *OneConnection) TryPing() bool {
	if common.PingPeerEvery == 0 {
		return false // pinging disabled in global config
	}

	if c.Node.Version <= 60000 {
		return false // insufficient protocol version
	}

	if time.Now().Before(c.LastPingSent.Add(common.PingPeerEvery)) {
		return false // not yet...
	}

	if c.PingInProgress != nil {
		if common.DebugLevel > 0 {
			println(c.PeerAddr.Ip(), "ping timeout")
		}
		common.CountSafe("PingTimeout")
		c.HandlePong() // this will set PingInProgress to nil
	}

	c.PingInProgress = make([]byte, 8)
	rand.Read(c.PingInProgress[:])
	c.SendRawMsg("ping", c.PingInProgress)
	c.LastPingSent = time.Now()
	//println(c.PeerAddr.Ip(), "ping...")
	return true
}
Пример #18
0
func (c *OneConnection) Misbehave(why string, how_much int) (res bool) {
	c.Mutex.Lock()
	if !c.banit {
		common.CountSafe("Bad" + why)
		c.misbehave += how_much
		if c.misbehave >= 1000 {
			common.CountSafe("BanMisbehave")
			res = true
			c.banit = true
			c.broken = true
			//print("Ban " + c.PeerAddr.Ip() + " (" + c.Node.Agent + ") because " + why + "\n> ")
		}
	}
	c.Mutex.Unlock()
	return
}
Пример #19
0
// This function should be called only when OutConsActive >= MaxOutCons
func drop_slowest_peer() {
	var worst_ping int
	var worst_conn *OneConnection
	Mutex_net.Lock()
	for _, v := range OpenCons {
		if v.Incoming && InConsActive < atomic.LoadUint32(&common.CFG.Net.MaxInCons) {
			// If this is an incoming connection, but we are not full yet, ignore it
			continue
		}
		v.Mutex.Lock()
		ap := v.GetAveragePing()
		v.Mutex.Unlock()
		if ap > worst_ping {
			worst_ping = ap
			worst_conn = v
		}
	}
	if worst_conn != nil {
		if common.DebugLevel > 0 {
			println("Droping slowest peer", worst_conn.PeerAddr.Ip(), "/", worst_ping, "ms")
		}
		worst_conn.Disconnect()
		common.CountSafe("PeersDropped")
	}
	Mutex_net.Unlock()
}
Пример #20
0
func RetryWaitingForInput(wtg *OneWaitingList) {
	for k, t := range wtg.Ids {
		pendtxrcv := TransactionsRejected[k].Wait4Input.TxRcvd
		if HandleNetTx(pendtxrcv, true) {
			common.CountSafe("TxRetryAccepted")
			if common.DebugLevel > 0 {
				fmt.Println(pendtxrcv.tx.Hash.String(), "accepted after", time.Now().Sub(t).String())
			}
		} else {
			common.CountSafe("TxRetryRejected")
			if common.DebugLevel > 0 {
				fmt.Println(pendtxrcv.tx.Hash.String(), "still rejected", TransactionsRejected[k].Reason)
			}
		}
	}
}
Пример #21
0
func (c *OneConnection) DoS() {
	common.CountSafe("BannedNodes")
	c.Mutex.Lock()
	c.banit = true
	c.broken = true
	c.Mutex.Unlock()
}
Пример #22
0
// Called from the blockchain thread
func HandleNetBlock(newbl *network.BlockRcvd) {
	common.CountSafe("HandleNetBlock")
	bl := newbl.Block
	common.Busy("CheckBlock " + bl.Hash.String())
	e, dos, maybelater := common.BlockChain.CheckBlock(bl)
	if e != nil {
		if maybelater {
			network.AddBlockToCache(bl, newbl.Conn)
		} else {
			fmt.Println(dos, e.Error())
			if dos {
				newbl.Conn.DoS("CheckBlock")
			}
		}
	} else {
		common.Busy("LocalAcceptBlock " + bl.Hash.String())
		e = LocalAcceptBlock(bl, newbl.Conn)
		if e == nil {
			retryCachedBlocks = retry_cached_blocks()
		} else {
			fmt.Println("AcceptBlock:", e.Error())
			newbl.Conn.DoS("LocalAcceptBl")
		}
	}
}
Пример #23
0
func EC_Verify(k, s, h []byte) bool {
	res := newec.Verify(k, s, h)
	if !res {
		common.CountSafe("ECVerifyFail")
	}
	return res
}
Пример #24
0
func (c *OneConnection) DoS(why string) {
	common.CountSafe("Ban" + why)
	c.Mutex.Lock()
	c.banit = true
	c.broken = true
	c.Mutex.Unlock()
}
Пример #25
0
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
}
Пример #26
0
func (c *OneConnection) SendInvs() (res bool) {
	b_txs := new(bytes.Buffer)
	b_blk := new(bytes.Buffer)
	var c_blk []*btc.Uint256

	c.Mutex.Lock()
	if len(c.PendingInvs) > 0 {
		for i := range c.PendingInvs {
			var inv_sent_otherwise bool
			typ := binary.LittleEndian.Uint32((*c.PendingInvs[i])[:4])
			c.InvStore(typ, (*c.PendingInvs[i])[4:36])
			if typ == MSG_BLOCK {
				if c.Node.SendCmpctVer >= 1 && c.Node.HighBandwidth {
					c_blk = append(c_blk, btc.NewUint256((*c.PendingInvs[i])[4:]))
					inv_sent_otherwise = true
				} else if c.Node.SendHeaders {
					// convert block inv to block header
					common.BlockChain.BlockIndexAccess.Lock()
					bl := common.BlockChain.BlockIndex[btc.NewUint256((*c.PendingInvs[i])[4:]).BIdx()]
					if bl != nil {
						b_blk.Write(bl.BlockHeader[:])
						b_blk.Write([]byte{0}) // 0 txs
					}
					common.BlockChain.BlockIndexAccess.Unlock()
					inv_sent_otherwise = true
				}
			}

			if !inv_sent_otherwise {
				b_txs.Write((*c.PendingInvs[i])[:])
			}
		}
		res = true
	}
	c.PendingInvs = nil
	c.Mutex.Unlock()

	if len(c_blk) > 0 {
		for _, h := range c_blk {
			c.SendCmpctBlk(h)
		}
	}

	if b_blk.Len() > 0 {
		common.CountSafe("InvSentAsHeader")
		b := new(bytes.Buffer)
		btc.WriteVlen(b, uint64(b_blk.Len()/81))
		c.SendRawMsg("headers", append(b.Bytes(), b_blk.Bytes()...))
		//println("sent block's header(s)", b_blk.Len(), uint64(b_blk.Len()/81))
	}

	if b_txs.Len() > 0 {
		b := new(bytes.Buffer)
		btc.WriteVlen(b, uint64(b_txs.Len()/36))
		c.SendRawMsg("inv", append(b.Bytes(), b_txs.Bytes()...))
	}

	return
}
Пример #27
0
func (c *OneConnection) DoS(why string) {
	common.CountSafe("Ban" + why)
	c.Mutex.Lock()
	c.banit = true
	c.broken = true
	//print("BAN " + c.PeerAddr.Ip() + " (" + c.Node.Agent + ") because " + why + "\n> ")
	c.Mutex.Unlock()
}
Пример #28
0
// Expire cached blocks
func ExpireCachedBlocks() {
	for k, v := range CachedBlocks {
		if v.Time.Add(ExpireCachedAfter).Before(time.Now()) {
			delete(CachedBlocks, k)
			common.CountSafe("BlockExpired")
		}
	}
}
Пример #29
0
// Called from network threads
func blockWanted(h []byte) (yes bool) {
	idx := btc.NewUint256(h).BIdx()
	MutexRcv.Lock()
	_, ok := ReceivedBlocks[idx]
	MutexRcv.Unlock()
	if !ok {
		if atomic.LoadUint32(&common.CFG.Net.MaxBlockAtOnce) == 0 || !blocksLimitReached(idx) {
			yes = true
			common.CountSafe("BlockWanted")
		} else {
			common.CountSafe("BlockInProgress")
		}
	} else {
		common.CountSafe("BlockUnwanted")
	}
	return
}
Пример #30
0
func isRoutable(rec *OneTxToSend) bool {
	if !common.CFG.TXRoute.Enabled {
		common.CountSafe("TxRouteDisabled")
		rec.Blocked = TX_REJECTED_DISABLED
		return false
	}
	if uint32(len(rec.Data)) > atomic.LoadUint32(&common.CFG.TXRoute.MaxTxSize) {
		common.CountSafe("TxRouteTooBig")
		rec.Blocked = TX_REJECTED_TOO_BIG
		return false
	}
	if rec.Fee < (uint64(rec.VSize()) * atomic.LoadUint64(&common.CFG.TXRoute.FeePerByte)) {
		common.CountSafe("TxRouteLowFee")
		rec.Blocked = TX_REJECTED_LOW_FEE
		return false
	}
	return true
}