예제 #1
0
파일: qdb_unspent.go 프로젝트: wchh/gocoin
func (db *UnspentDB) del(hash []byte, outs []bool) {
	if db.ch.CB.NotifyTxDel != nil {
		db.ch.CB.NotifyTxDel(hash, outs)
	}
	ind := qdb.KeyType(binary.LittleEndian.Uint64(hash[:8]))
	_db := db.dbN(int(hash[31]) % NumberOfUnspentSubDBs)
	v := _db.Get(ind)
	if v == nil {
		return // no such txid in UTXO (just ignorde delete request)
	}
	rec := NewQdbRec(ind, v)
	var anyout bool
	for i, rm := range outs {
		if rm {
			rec.Outs[i] = nil
		} else if rec.Outs[i] != nil {
			anyout = true
		}
	}
	if anyout {
		_db.Put(ind, rec.Bytes())
	} else {
		_db.Del(ind)
	}
}
예제 #2
0
파일: addr.go 프로젝트: wchh/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")
		}
	}
}
예제 #3
0
파일: qdb_unspent.go 프로젝트: wchh/gocoin
func (db *UnspentDB) UndoBlockTxs(bl *btc.Block, newhash []byte) {
	for _, tx := range bl.Txs {
		lst := make([]bool, len(tx.TxOut))
		for i := range lst {
			lst[i] = true
		}
		db.del(tx.Hash.Hash[:], lst)
	}

	fn := fmt.Sprint(db.dir, db.LastBlockHeight)
	var addback []*QdbRec

	if _, er := os.Stat(fn); er != nil {
		fn += ".tmp"
	}

	dat, er := ioutil.ReadFile(fn)
	if er != nil {
		panic(er.Error())
	}

	off := 32 // ship the block hash
	for off < len(dat) {
		le, n := btc.VLen(dat[off:])
		off += n
		qr := FullQdbRec(dat[off : off+le])
		off += le
		addback = append(addback, qr)
	}

	for _, tx := range addback {
		if db.ch.CB.NotifyTxAdd != nil {
			db.ch.CB.NotifyTxAdd(tx)
		}

		ind := qdb.KeyType(binary.LittleEndian.Uint64(tx.TxID[:8]))
		_db := db.dbN(int(tx.TxID[31]) % NumberOfUnspentSubDBs)
		v := _db.Get(ind)
		if v != nil {
			oldrec := NewQdbRec(ind, v)
			for a := range tx.Outs {
				if tx.Outs[a] == nil {
					tx.Outs[a] = oldrec.Outs[a]
				}
			}
		}
		_db.PutExt(ind, tx.Bytes(), 0)
	}

	os.Remove(fn)
	db.LastBlockHeight--
	copy(db.LastBlockHash, newhash)
}
예제 #4
0
파일: qdb_unspent.go 프로젝트: wchh/gocoin
func (db *UnspentDB) commit(changes *BlockChanges) {
	// Now aplly the unspent changes
	for _, rec := range changes.AddList {
		ind := qdb.KeyType(binary.LittleEndian.Uint64(rec.TxID[:8]))
		if db.ch.CB.NotifyTxAdd != nil {
			db.ch.CB.NotifyTxAdd(rec)
		}
		db.dbN(int(rec.TxID[31])%NumberOfUnspentSubDBs).PutExt(ind, rec.Bytes(), 0)
	}
	for k, v := range changes.DeledTxs {
		db.del(k[:], v)
	}
}
예제 #5
0
파일: peerdb.go 프로젝트: wchh/gocoin
func NewPeerFromString(ipstr string, force_default_port bool) (p *PeerAddr, e error) {
	port := DefaultTcpPort()
	x := strings.Index(ipstr, ":")
	if x != -1 {
		if !force_default_port {
			v, er := strconv.ParseUint(ipstr[x+1:], 10, 32)
			if er != nil {
				e = er
				return
			}
			if v > 0xffff {
				e = errors.New("Port number too big")
				return
			}
			port = uint16(v)
		}
		ipstr = ipstr[:x] // remove port number
	}
	ip := net.ParseIP(ipstr)
	if ip != nil && len(ip) == 16 {
		if sys.IsIPBlocked(ip[12:16]) {
			e = errors.New(ipstr + " is blocked")
			return
		}
		p = NewEmptyPeer()
		copy(p.Ip4[:], ip[12:16])
		p.Services = Services
		copy(p.Ip6[:], ip[:12])
		p.Port = port
		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
}
예제 #6
0
파일: qdb_unspent.go 프로젝트: wchh/gocoin
// Get ne unspent output
func (db *UnspentDB) UnspentGet(po *btc.TxPrevOut) (res *btc.TxOut, e error) {
	ind := qdb.KeyType(binary.LittleEndian.Uint64(po.Hash[:8]))
	v := db.dbN(int(po.Hash[31]) % NumberOfUnspentSubDBs).Get(ind)
	if v == nil {
		e = errors.New("Unspent TX not found")
		return
	}

	rec := NewQdbRec(ind, v)
	if len(rec.Outs) < int(po.Vout) || rec.Outs[po.Vout] == nil {
		e = errors.New("Unspent VOut not found")
		return
	}
	res = new(btc.TxOut)
	res.VoutCount = uint32(len(rec.Outs))
	res.WasCoinbase = rec.Coinbase
	res.BlockHeight = rec.InBlock
	res.Value = rec.Outs[po.Vout].Value
	res.Pk_script = rec.Outs[po.Vout].PKScr
	return
}
예제 #7
0
파일: addr.go 프로젝트: wchh/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
				}
				peersdb.PeerDB.Put(k, a.Bytes())
			} else {
				common.CountSafe("AddrStale")
			}
		} else {
			if c.Misbehave("AddrFuture", 50) {
				break
			}
		}
	}
}
예제 #8
0
파일: peerdb.go 프로젝트: wchh/gocoin
func (p *PeerAddr) Save() {
	PeerDB.Put(qdb.KeyType(p.UniqID()), p.Bytes())
}
예제 #9
0
파일: qdb_record.go 프로젝트: wchh/gocoin
func FullQdbRec(dat []byte) *QdbRec {
	return NewQdbRec(qdb.KeyType(binary.LittleEndian.Uint64(dat[:8])), dat[8:])
}