Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

udb: use a credit iterator for detached credits. #1479

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion wallet/rescan.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package wallet

import (
"encoding/binary"
"context"
"time"

Expand Down Expand Up @@ -62,6 +63,20 @@ func NewRescanFilter(addresses []dcrutil.Address, unspentOutPoints []*wire.OutPo
return filter
}

// extractBlockHeaderHeight fetches the block height from wire encoded block
// header bytes.
func extractBlockHeaderHeight(header []byte) int32 {
const heightOffset = 128
return int32(binary.LittleEndian.Uint32(header[heightOffset:]))
}

// extractBlockHeaderUnixTime fetches the unix timestamp from wire encoded
// block header bytes.
func extractBlockHeaderUnixTime(header []byte) uint32 {
const timestampOffset = 136
return binary.LittleEndian.Uint32(header[timestampOffset:])
}

// AddAddress adds an address to the filter if it does not already exist.
func (f *RescanFilter) AddAddress(a dcrutil.Address) {
switch a := a.(type) {
Expand Down Expand Up @@ -269,7 +284,7 @@ func (w *Wallet) Rescan(ctx context.Context, n NetworkBackend, startHash *chainh
if err != nil {
return err
}
startHeight = udb.ExtractBlockHeaderHeight(header)
startHeight = extractBlockHeaderHeight(header)
return nil
})
if err != nil {
Expand Down
67 changes: 35 additions & 32 deletions wallet/udb/txmined.go
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,7 @@ func extractBlockHeaderParentHash(header []byte) []byte {
// ExtractBlockHeaderParentHash subslices the header to return the bytes of the
// parent block's hash. Must only be called on known good input.
//
// TODO: This really should not be exported by this package.
// DEPRECATED: to be removed in the next major release.
func ExtractBlockHeaderParentHash(header []byte) []byte {
return extractBlockHeaderParentHash(header)
}
Expand All @@ -476,7 +476,7 @@ func extractBlockHeaderHeight(header []byte) int32 {
// ExtractBlockHeaderHeight returns the height field that is encoded in the
// header. Must only be called on known good input.
//
// TODO: This really should not be exported by this package.
// DEPRECATED: to be removed in the next major release.
func ExtractBlockHeaderHeight(header []byte) int32 {
return extractBlockHeaderHeight(header)
}
Expand All @@ -490,7 +490,7 @@ func extractBlockHeaderUnixTime(header []byte) uint32 {
// header. Must only be called on known good input. Header timestamps are only
// 4 bytes and this value is actually limited to a maximum unix time of 2^32-1.
//
// TODO: This really should not be exported by this package.
// DEPRECATED: to be removed in the next major release.
func ExtractBlockHeaderTime(header []byte) int64 {
return int64(extractBlockHeaderUnixTime(header))
}
Expand Down Expand Up @@ -1984,39 +1984,39 @@ func (s *Store) rollback(ns walletdb.ReadWriteBucket, addrmgrNs walletdb.ReadBuc
// credit output to unmined. If the credit is marked
// unspent, it is removed from the utxo set and the
// mined balance is decremented.
//
// TODO: use a credit iterator
for i, output := range rec.MsgTx.TxOut {
k, v := existsCredit(ns, &rec.Hash, uint32(i),
&b.Block)
if v == nil {
continue
k := keyTxRecord(&rec.Hash, &b.Block)
credIter := makeReadCreditIterator(ns, k, DBVersion)
defer credIter.close()
for credIter.next() {
if int(credIter.elem.Index) >= len(rec.MsgTx.TxOut) {
credIter.close()
return errors.E(errors.IO,
"saved credit index exceeds number of outputs")
}
vcopy := make([]byte, len(v))
copy(vcopy, v)
removedCredits[string(k)] = vcopy

amt, change, err := fetchRawCreditAmountChange(v)
// scrType := pkScriptType(output.PkScript)
scrPos := fetchRawCreditScriptOffset(credIter.cv)
scrLen := fetchRawCreditScriptLength(credIter.cv)

pkScript, err := fetchRawTxRecordPkScript(credIter.ck,
credIter.cv, credIter.elem.Index, scrPos, scrLen)
if err != nil {
return err
}
opCode := fetchRawCreditTagOpCode(v)
isCoinbase := fetchRawCreditIsCoinbase(v)
hasExpiry := fetchRawCreditHasExpiry(v, DBVersion)

scrType := pkScriptType(output.PkScript)
scrLoc := rec.MsgTx.PkScriptLocs()[i]
scrLen := len(rec.MsgTx.TxOut[i].PkScript)

acct, err := s.fetchAccountForPkScript(addrmgrNs, v, nil, output.PkScript)
acct, err := s.fetchAccountForPkScript(addrmgrNs, credIter.cv,
nil, pkScript)
if err != nil {
return err
}

outPointKey := canonicalOutPoint(&rec.Hash, uint32(i))
unminedCredVal := valueUnminedCredit(amt, change, opCode,
isCoinbase, hasExpiry, scrType, uint32(scrLoc), uint32(scrLen),
acct, DBVersion)
scrType := pkScriptType(pkScript)
scrLoc := rec.MsgTx.PkScriptLocs()[credIter.elem.Index]
outPointKey := canonicalOutPoint(&rec.Hash, credIter.elem.Index)
unminedCredVal := valueUnminedCredit(credIter.elem.Amount,
credIter.elem.Change, credIter.elem.OpCode,
credIter.elem.IsCoinbase, credIter.elem.HasExpiry, scrType,
uint32(scrLoc), uint32(scrLen), acct, DBVersion)
err = putRawUnminedCredit(ns, outPointKey, unminedCredVal)
if err != nil {
return err
Expand All @@ -2031,20 +2031,20 @@ func (s *Store) rollback(ns walletdb.ReadWriteBucket, addrmgrNs walletdb.ReadBuc
if credKey != nil {
// Ticket amounts were never added, so ignore them when
// correcting the balance.
isTicketOutput := (txType == stake.TxTypeSStx && i == 0)
isTicketOutput := (txType == stake.TxTypeSStx &&
credIter.elem.Index == 0)
if !isTicketOutput {
minedBalance -= dcrutil.Amount(output.Value)
minedBalance -= credIter.elem.Amount
}
err = deleteRawUnspent(ns, outPointKey)
if err != nil {
return err
}
}

// Check if this output is a multisignature
// P2SH output. If it is, access the value
// for the key and mark it unmined.
msKey := keyMultisigOut(*txHash, uint32(i))
// Check if this output is a multisignature P2SH output.
// If it is, access the value for the key and mark it unmined.
msKey := keyMultisigOut(*txHash, uint32(credIter.elem.Index))
msVal := existsMultisigOutCopy(ns, msKey)
if msVal != nil {
setMultisigOutUnmined(msVal)
Expand All @@ -2054,6 +2054,9 @@ func (s *Store) rollback(ns walletdb.ReadWriteBucket, addrmgrNs walletdb.ReadBuc
}
}
}
if credIter.err != nil {
return credIter.err
}

// When rolling back votes and revocations, return unspent status
// for tracked commitments.
Expand Down
4 changes: 2 additions & 2 deletions wallet/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -2223,7 +2223,7 @@ func (w *Wallet) BlockInfo(blockID *BlockIdentifier) (*BlockInfo, error) {
if err != nil {
return err
}
height := udb.ExtractBlockHeaderHeight(header)
height := extractBlockHeaderHeight(header)
inMainChain, invalidated := w.TxStore.BlockInMainChain(dbtx, blockHash)
var confs int32
if inMainChain {
Expand All @@ -2234,7 +2234,7 @@ func (w *Wallet) BlockInfo(blockID *BlockIdentifier) (*BlockInfo, error) {
Height: height,
Confirmations: confs,
Header: header,
Timestamp: udb.ExtractBlockHeaderTime(header),
Timestamp: int64(extractBlockHeaderUnixTime(header)),
StakeInvalidated: invalidated,
}
return nil
Expand Down