func (db *unspentDb) del(idx *btc.TxPrevOut) { if db.ch.CB.NotifyTx != nil { db.ch.CB.NotifyTx(idx, nil) } key := qdb.KeyType(idx.UIdx()) db.dbN(int(idx.Hash[31]) % NumberOfUnspentSubDBs).Del(key) }
func (db *unspentDb) add(idx *btc.TxPrevOut, Val_Pk *btc.TxOut) { v := make([]byte, SCR_OFFS+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[SCR_OFFS:], Val_Pk.Pk_script) k := qdb.KeyType(idx.UIdx()) var flgz uint32 dbN := db.dbN(int(idx.Hash[31]) % NumberOfUnspentSubDBs) if stealthIndex(v) { if db.ch.CB.NotifyStealthTx != nil { db.ch.CB.NotifyStealthTx(dbN, k, NewWalkRecord(v)) } flgz = qdb.YES_CACHE | qdb.YES_BROWSE } else { if db.ch.CB.NotifyTx != nil { db.ch.CB.NotifyTx(idx, Val_Pk) } if Val_Pk.Value < MinBrowsableOutValue { flgz = qdb.NO_CACHE | qdb.NO_BROWSE } else if NocacheBlocksBelow == -1 { flgz = qdb.NO_CACHE | qdb.NO_BROWSE } } dbN.PutExt(k, v, flgz) }
// Return txs in mempool that are spending any outputs form the given tx func findPendingTxs(tx *btc.Tx) (res []BIDX) { var in btc.TxPrevOut copy(in.Hash[:], tx.Hash.Hash[:]) for in.Vout = 0; in.Vout < uint32(len(tx.TxOut)); in.Vout++ { if r, ok := SpentOutputs[in.UIdx()]; ok { res = append(res, r) } } return res }
// This is called while accepting the block (from the chain's thread) func TxNotify(idx *btc.TxPrevOut, valpk *btc.TxOut) { var update_wallet bool BalanceMutex.Lock() if valpk != nil { // Extract hash160 from pkscript adr := btc.NewAddrFromPkScript(valpk.Pk_script, common.Testnet) if adr != nil { if rec, ok := CachedAddrs[adr.Hash160]; ok { rec.Value += valpk.Value utxo := new(chain.OneUnspentTx) utxo.TxPrevOut = *idx utxo.Value = valpk.Value utxo.MinedAt = valpk.BlockHeight utxo.BtcAddr = CacheUnspent[rec.CacheIndex].BtcAddr CacheUnspent[rec.CacheIndex].AllUnspentTx = append(CacheUnspent[rec.CacheIndex].AllUnspentTx, utxo) CacheUnspentIdx[idx.UIdx()] = &OneCachedUnspentIdx{Index: rec.CacheIndex, Record: utxo} if rec.InWallet { update_wallet = true } } } } else { ii := idx.UIdx() if ab, present := CacheUnspentIdx[ii]; present { adrec := CacheUnspent[ab.Index] //println("removing", idx.String()) rec := CachedAddrs[adrec.BtcAddr.Hash160] if rec == nil { panic("rec not found for " + adrec.BtcAddr.String()) } rec.Value -= ab.Record.Value if rec.InWallet { update_wallet = true } for j := range adrec.AllUnspentTx { if adrec.AllUnspentTx[j] == ab.Record { //println("found it at index", j) adrec.AllUnspentTx = append(adrec.AllUnspentTx[:j], adrec.AllUnspentTx[j+1:]...) break } } delete(CacheUnspentIdx, ii) } } if update_wallet { sync_wallet() } BalanceMutex.Unlock() }
func (db *unspentDb) get(po *btc.TxPrevOut) (res *btc.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) < SCR_OFFS { panic(fmt.Sprint("unspent record too short:", len(val))) } res = new(btc.TxOut) res.Value = binary.LittleEndian.Uint64(val[36:44]) res.BlockHeight = binary.LittleEndian.Uint32(val[44:48]) res.Pk_script = make([]byte, len(val)-SCR_OFFS) copy(res.Pk_script, val[SCR_OFFS:]) return }
// This is called while accepting the block (from the chain's thread) func TxNotifyDel(txid []byte, outs []bool) { var update_wallet bool BalanceMutex.Lock() var uidx btc.TxPrevOut copy(uidx.Hash[:], txid) for uidx.Vout = 0; uidx.Vout < uint32(len(outs)); uidx.Vout++ { if outs[uidx.Vout] { ii := uidx.UIdx() if ab, present := CacheUnspentIdx[ii]; present { adrec := CacheUnspent[ab.Index] rec := CachedAddrs[adrec.BtcAddr.Hash160] if rec == nil { panic("rec not found for " + adrec.BtcAddr.String()) } rec.Value -= ab.Record.Value if rec.InWallet { update_wallet = true } for j := range adrec.AllUnspentTx { if adrec.AllUnspentTx[j] == ab.Record { //println("found it at index", j) adrec.AllUnspentTx = append(adrec.AllUnspentTx[:j], adrec.AllUnspentTx[j+1:]...) break } } delete(CacheUnspentIdx, ii) } } } if update_wallet { sync_wallet() } BalanceMutex.Unlock() }