func (c *oneConnection) VerMsg(pl []byte) error { if len(pl) >= 46 { c.node.version = binary.LittleEndian.Uint32(pl[0:4]) c.node.services = binary.LittleEndian.Uint64(pl[4:12]) c.node.timestamp = binary.LittleEndian.Uint64(pl[12:20]) if MyExternalAddr == nil { MyExternalAddr = btc.NewNetAddr(pl[20:46]) // These bytes should know our external IP MyExternalAddr.Port = DefaultTcpPort } if len(pl) >= 86 { //fmt.Println("From:", btc.NewNetAddr(pl[46:72]).String()) //fmt.Println("Nonce:", hex.EncodeToString(pl[72:80])) 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]) /*of += 4 if len(pl) >= of+1 { fmt.Println("Relay:", pl[of]) }*/ } } } else { return errors.New("Version message too short") } c.SendRawMsg("verack", []byte{}) if c.listen { c.SendVersion() } return nil }
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 }
func (c *oneConnection) ProcessInv(pl []byte) { if len(pl) < 37 { println("inv payload too short") return } cnt, of := btc.VLen(pl) if len(pl) != of+36*cnt { println("inv payload length mismatch", len(pl), of, cnt) } var blocks2get [][32]byte var txs uint32 for i := 0; i < cnt; i++ { typ := binary.LittleEndian.Uint32(pl[of : of+4]) if typ == 2 { if InvsNotify(pl[of+4 : of+36]) { var inv [32]byte copy(inv[:], pl[of+4:of+36]) blocks2get = append(blocks2get, inv) } } else { txs++ } of += 36 } if dbg > 1 { println(c.addr.Ip(), "ProcessInv:", cnt, "tot /", txs, "txs -> get", len(blocks2get), "blocks") } if len(blocks2get) > 0 { msg := make([]byte, 9 /*maxvlen*/ +len(blocks2get)*36) le := btc.PutVlen(msg, len(blocks2get)) for i := range blocks2get { binary.LittleEndian.PutUint32(msg[le:le+4], 2) copy(msg[le+4:le+36], blocks2get[i][:]) le += 36 } if dbg > 0 { println("getdata for", len(blocks2get), "/", cnt, "blocks", le) } c.SendRawMsg("getdata", msg[:le]) } return }
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.Mutex.Unlock() if ValidIp4(pl[40:44]) { ExternalIpMutex.Lock() ip4 := binary.BigEndian.Uint32(pl[40:44]) ExternalIp4[ip4] = [2]uint{ExternalIp4[ip4][0] + 1, uint(time.Now().Unix())} ExternalIpMutex.Unlock() } if len(pl) >= 86 { c.Mutex.Lock() 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]) of += 4 if len(pl) > of && pl[of] == 0 { c.Node.DoNotRelayTxs = true } } c.Mutex.Unlock() } } else { return errors.New("common.Version message too short") } c.SendRawMsg("verack", []byte{}) return nil }