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()) }
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) }
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()) } }
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()) }
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()) } }
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 }
// 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 }
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 }
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 *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) } }
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() }
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 }
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()) } }