func NewIncomingPeer(ipstr string) (p *onePeer, e error) { x := strings.Index(ipstr, ":") if x != -1 { ipstr = ipstr[:x] // remove port number } ip := net.ParseIP(ipstr) if ip != nil && len(ip) == 16 { if common.IsIPBlocked(ip[12:16]) { e = errors.New(ipstr + " is blocked") return } p = new(onePeer) copy(p.Ip4[:], ip[12:16]) p.Services = common.Services copy(p.Ip6[:], ip[:12]) p.Port = common.DefaultTcpPort if dbp := PeerDB.Get(qdb.KeyType(p.UniqID())); dbp != nil && NewPeer(dbp).Banned != 0 { e = errors.New(p.Ip() + " is banned") p = nil } else { p.Time = uint32(time.Now().Unix()) p.Save() } } else { e = errors.New("Error parsing IP '" + ipstr + "'") } return }
// 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") } } }
func (db *unspentDb) del(idx *TxPrevOut) { if db.notifyTx != nil { db.notifyTx(idx, nil) } key := qdb.KeyType(idx.UIdx()) db.dbN(int(idx.Hash[31]) % NumberOfUnspentSubDBs).Del(key) }
func (db *unwindDb) undo(height uint32, unsp *unspentDb) { if height != db.lastBlockHeight { panic("Unexpected height") } v := db.dbH(int(height) % NumberOfUnwindSubDBs).Get(qdb.KeyType(height)) if v == nil { panic("Unwind data not found") } unwindFromReader(bytes.NewReader(v[32:]), unsp) db.del(height) db.lastBlockHeight-- v = db.dbH(int(db.lastBlockHeight) % NumberOfUnwindSubDBs).Get(qdb.KeyType(db.lastBlockHeight)) if v == nil { panic("Parent data not found") } copy(db.lastBlockHash[:], v[:32]) return }
func (db *unspentDb) scanstealth(sa *StealthAddr, walk func([]byte, []byte, uint32, []byte) bool) { for i := range db.tdb { db.dbN(i).Browse(func(k qdb.KeyType, v []byte) uint32 { if stealthIndex(v) { vo := binary.LittleEndian.Uint32(v[32:36]) spend_v := db.dbN(i).GetNoMutex(qdb.KeyType(uint64(k) ^ uint64(vo) ^ uint64(vo+1))) if spend_v == nil { return qdb.NO_CACHE | qdb.NO_BROWSE } else if sa.CheckNonce(v[51:]) { if !walk(v[55:], spend_v[0:32], vo+1, spend_v[48:]) { return qdb.NO_CACHE | qdb.NO_BROWSE } } } return 0 }) } }
func (db *unspentDb) get(po *TxPrevOut) (res *TxOut, e error) { ind := qdb.KeyType(po.UIdx()) val := db.dbN(int(po.Hash[31]) % NumberOfUnspentSubDBs).Get(ind) if val == nil { e = errors.New("Unspent not found") return } if len(val) < 48 { panic(fmt.Sprint("unspent record too short:", len(val))) } res = new(TxOut) res.Value = binary.LittleEndian.Uint64(val[36:44]) res.BlockHeight = binary.LittleEndian.Uint32(val[44:48]) res.Pk_script = make([]byte, len(val)-48) copy(res.Pk_script, val[48:]) return }
func (db *unwindDb) commit(changes *btc.BlockChanges, blhash []byte) { if db.lastBlockHeight+1 != changes.Height { println(db.lastBlockHeight+1, changes.Height) panic("Unexpected height") } db.lastBlockHeight++ copy(db.lastBlockHash[:], blhash[0:32]) f := new(bytes.Buffer) f.Write(blhash[0:32]) for k, _ := range changes.AddedTxs { writeSpent(f, &k, nil) } for k, v := range changes.DeledTxs { writeSpent(f, &k, v) } db.dbH(int(changes.Height)%NumberOfUnwindSubDBs).PutExt(qdb.KeyType(changes.Height), f.Bytes(), qdb.NO_CACHE) if changes.Height >= UnwindBufferMaxHistory { db.del(changes.Height - UnwindBufferMaxHistory) } }
func (db *unspentDb) add(idx *TxPrevOut, Val_Pk *TxOut) { if db.notifyTx != nil { db.notifyTx(idx, Val_Pk) } v := make([]byte, 48+len(Val_Pk.Pk_script)) copy(v[0:32], idx.Hash[:]) binary.LittleEndian.PutUint32(v[32:36], idx.Vout) binary.LittleEndian.PutUint64(v[36:44], Val_Pk.Value) binary.LittleEndian.PutUint32(v[44:48], Val_Pk.BlockHeight) copy(v[48:], Val_Pk.Pk_script) ind := qdb.KeyType(idx.UIdx()) var flgz uint32 if stealthIndex(v) { flgz = qdb.YES_CACHE | qdb.YES_BROWSE } else { if Val_Pk.Value < MinBrowsableOutValue { flgz = qdb.NO_CACHE | qdb.NO_BROWSE } else if uint(Val_Pk.BlockHeight) < NocacheBlocksBelow { flgz = qdb.NO_CACHE } } db.dbN(int(idx.Hash[31])%NumberOfUnspentSubDBs).PutExt(ind, v, flgz) }
func (db *unwindDb) commit(changes *BlockChanges, blhash []byte) { if db.lastBlockHeight+1 != changes.Height { println(db.lastBlockHeight+1, changes.Height) panic("Unexpected height") } db.lastBlockHeight++ copy(db.lastBlockHash[:], blhash[0:32]) f := new(bytes.Buffer) f.Write(blhash[0:32]) // cast uin32 to int to properly discover negative diffs: if int(changes.LastKnownHeight)-int(changes.Height) < UnwindBufferMaxHistory { for k, _ := range changes.AddedTxs { writeSpent(f, &k, nil) } for k, v := range changes.DeledTxs { writeSpent(f, &k, v) } } db.dbH(int(changes.Height)%NumberOfUnwindSubDBs).PutExt(qdb.KeyType(changes.Height), f.Bytes(), qdb.NO_CACHE) if changes.Height >= UnwindBufferMaxHistory { db.del(changes.Height - UnwindBufferMaxHistory) } }
func (p *onePeer) Save() { PeerDB.Put(qdb.KeyType(p.UniqID()), p.Bytes()) }
func (db *unwindDb) del(height uint32) { db.tdb[height%NumberOfUnwindSubDBs].Del(qdb.KeyType(height)) }
func getUnspIndex(po *TxPrevOut) qdb.KeyType { return qdb.KeyType(binary.LittleEndian.Uint64(po.Hash[:8]) ^ uint64(po.Vout)) }