- insert
insert(pending)
: first sight of tx in mempool.insert(block)
: first sight of tx in block.
confirm
- confirm known transaction (from mempool, now in block)
unconfirm
- chain reorg
- rescan (consecutive reverts) - may change the behaviour.
erase(pending)
/erase(block)
- Saw in mempool, was double spent in block.
- Reverted wallet, was double spent in block.
- Reverted wallet, was zapped.
Entries marked with *
are not part of the first update.
-
insert (pending)
-tx++
Input
(detect usinggetCredit
)- It is spending our credit
(ub-, ulb-)
.- don't remove credit, but mark it as spent.
unconfirmed: -value
.unconfirmedLocked: -value
.coin--
- add to
spent credits
for this tx.
- *We have coinview information from the chain and we discovered it is ours.
(b+, lb+)
(Note 3)- Create credit
- emit
missed credit(block OR pending) -> pending(this)
(Note 5) - mark it as
spent
. confirmed: +value
confirmedLocked: +value
- don't increase coins or unconfirmed balances as this tx is spending it.
- add to
spent credits
for this tx.
- Unknown, but it is actually ours. (Same as below)
- We CAN'T do anything if don't have credit entry. (and even coinview did not help).
- It could be either in the pendings and we missed it that time (layout.s)
- It is already part of the block we wont get to see it anymore.
- Can't detect missed credit.
- Unknown - track for dbl spends.
- track for dbl spends (writeInputs/layout.s)
- do nothing.. (no value, cant create credit)
- It is spending our credit
Output
(detect usinggetPath
)- Our output
(ub+, ulb+)
.- Create credit.
- save credit as unconfirmed (coin.height = -1).
unconfirmed: +value
.unconfirmedLocked: +value
coin++
- NEW: Our output, but was already spent (missed on spend). (Note 5)
- Create credit.
- save credit as unconfirmed (coin.height = -1)
- mark it as
spent
. - add to
spent credits
for the spending transaction. - emit
missed credit(pending) -> pending
unconfirmed: -value
.unconfirmedLocked: -value
.coin--
- Unknown
- do nothing. (could be ours)
- Our output
-
insert (block)
-tx++
(no unconfirmed state for this)Input
(detect usinggetCredit
)- It is spending our credit
(b-, lb-, ub-, ulb-)
.- Remove credit.
confirmed: -value and unconfirmed: -value
confirmedLocked: -value and unconfirmedLocked: -value
coin--
- add to
spent coins
for this tx.
- *We have coinview information from the chain and we discovered it is ours. (Note 3)
- emit
missed credit(block) -> block
- add to
spent coins
for this tx.
- emit
- Unknown, but it is actually ours
- we can't do anything if it was not added to the credit list even now. (So it is part of the current block or previous ones)
- Unknown
- do nothing (not even track), we know it wont get double spent.
- no more opportunity to discover even if it was ours.
- It is spending our credit
Output
(detect usinggetPath
)- Our output
(b+, lb+, ub+, ulb+)
.- Create credit.
confirmed: +value and unconfirmed: +value
confirmedUnlocked: +value and unconfirmedLocked: +value
coin++
- NEW: Our output, but was already spent (missed on spend).
(b+, lb+)
(Note 4)- Create credit.
confirmed: +value
confirmedLocked: +value
- mark it as
spent
. - add to the
spent credits
for the spending transaction. - emit
missed credit(block) -> pending or block
- Unknown
- we do nothing.
- Our output
-
confirm
(prev inserted withinsert(pending)
from the mempool)Input
(detect usinggetCredit
)- It is spending our credit
(b-, lb-)
, indexed ininsert(block)
or prevconfirm
confirmed: -value
confirmedLocked: -value
- Remove credit.
- It is spending our credit
(b-, lb-, ub-?, ulb-?)
, but it was discovered afterinsert(pending)
ininsert(block)
,insert(pending)
orconfirm
.confirmed: -value
confirmedLocked: -value
- Resolve credit (insert(pending).out, insert(block).out, confirm.out)
coin--
unconfirmed: -value
unconfirmedLocked: -value
- This resolve is step where unconfirmed balance gets FIXED and output spent tracking is not strictly necessary as it will recover.
- *We have coinview information from the chain and we discovered it is ours.
(b+, lb+)
(Note 3)- emit
missed credit(block) -> block
- add to
spent coins
for this tx.
- emit
- Unknown, could be ours.
- do nothing.
- It is spending our credit
Output
(detect usinggetPath
)- Our output (tracked)
(b+, lb+)
:confirmed: +value
confirmedLocked: +value
updateSpentCoin
- if it was spent.
- Our output
(b+, lb+, ub+, ulb+)
, but was missed oninsert(pending)
NOT SPENT:- Create credit.
coin++
unconfirmed: +value
unconfirmedLocked: +value
confirmed: +value
confirmedLocked: +value
- emit
missed credit(block) -> null
- NEW: Our output, but was already spent.
(b+, lb+)
, was missed oninsert(pending)
- Create credit.
confirmed: +value
confirmedLocked: +value
- mark it as
spent.
- add to the
spent credits
for the spending transaction. - emit
missed credit(block) -> pending or block
- Unknown, could be ours
- we do nothing.
- Our output (tracked)
-
unconfirm
Input
(detect usinggetSpentCredits
)- Input is ours.
(b+, lb+)
- Grab spent credit.
- mark it as
spent
. confirmed: +value
(because on chain we no longer have this deduced, only unconfirmed)confirmedLocked: +value
(same as above)
- Unknown, can be ours.
- do nothing (store for double spends)
- Input is ours.
Output
(detect usinggetPath
)- Output is ours
(b-, lb-)
, we've got the credit.- Resave credit with updated height to the db.
confirmed: -value
confirmedLocked: -value
- We already have this in
unconfirmed/lockedUnconfirmed
balances, no need to modify. updateSpentCoin
- if it was spent.
- NEW: Output is ours, but we just discovered it
(ub+, ulb+)
and it's not spent.- Create credit for it.
unconfirmed: +value
unconfirmedLocked: +value
coin++
- Don't add to confirmed/confirmedLocked because we just discovered and it's not confirmed.
- emit
missed credit(pending) -> null
- NEW: Output is ours, but we just discovered it and it's spent.
- Create credit for it.
- mark it as
spent.
- add to the
spent credits
for the spending transaction. - emit
missed credit(pending) -> pending
- Don't touch balances, it's not part of confirmed because it's not confirmed and not part of unconfirmed because it is spent.
- Output is not ours
- Do nothing.
- Output is ours
-
erase(pending)
-tx--
-
Input
(detect usinggetSpentCredits
)- Input is ours. (
ub+, ulb+
)- Get spent credits and resave them as credits.
- unmark it as
spent
if it was ever marked. unconfirmed: +value
unconfirmedLocked: +value
coin++
updateSpentCoin
- Input is not ours. (could be, we can't know)
- Do nothing.
- Input is ours. (
-
Output
(detect usinggetPath
)- Output is ours
(ub-, ulb-)
.- Remove credit.
coin--
unconfirmed: -value
unconfirmedLocked: -value
- Output is ours, we just discovered it (not spent)
- Do nothing, as would have been discarded.
- Output is ours, we just discover it and it is SPENT
- If output is spent by us in pending, remove them recursively as they are now orphaned.
- This is done by the
remove
method which is called in case of zap/abandon
- Output is not ours.
- Do nothing.
- Output is ours
-
erase(block)
-tx--
Input
(detect usinggetSpentCredits
)- Input is ours. (
b+, lb+, ub+, ulb+
)- Get spent credit and resave them as credits.
unconfirmed: +value
unconfirmedLocked: +value
confirmed: +value
confirmedLocked: +value
- Input is not ours.
- Do nothing.
- Input is ours. (
Output
(detect usinggetPath
)- Output is ours (
b-, lb-, ub-, ulb-
)- Remove credit
coin--
confirmed: -value
confirmedLocked: -value
unconfirmed: -value
unconfirmedLocked: -value
- Out is ours we just discovered it (not spent).
- Do nothing, as would have been discarded.
- Out is ours we just discovered it and it is SPENT.
- If output is spent by us in pending, remove them recursively.
- This is done by the
remove
method which is called in case of zap/abandon
- Output is not ours.
- Do nothing.
- Output is ours (
-
NOTE 1: Transactions where we have missed inputs and outputs, will not get tracked by the wallet. E.g. we should have received money, but we were not tracking it with filters, this transaction and coin will be lost in history until rescan.
NOTE 2: mempool wont send us Orphaned transactions (where tx inputs are not part of the chain or mempool). This does not miss wallet can't be missing input or coins, if the derivation order is messed up.
NOTE 3: Currently, information from the chain does not include coinview, even when it is running full node with coin information. We could potentially include coinview for the blocks with transactions to allow better discoveries.
NOTE 4: Spent pending credit discoveries currently are not tracked, but they only affect unconfirmed amount until they are confirmed. Confirmed balances are correct.
NOTE 5: emit missed credit(credit state) -> spender state if any
State from lib/wallet/layout.js
txdb layout:
- layout.s :
- key - outpoint({input.prevout.hash, input.prevout.index})
- value - spender(input{txhash, inputIdx}) - double spend watch
- layout.d : spender(input{txhash, inputIdx}) -> credit.coin
- layout.c : coin(hash, index) -> credit
- layout.C : coin(account.id, hash, index) -> null
- layout.W : wid -> wallet balance
- layout.r : account.id -> account balance.
- NONE
- CLAIM
- BID
- REVEAL
- REDEEM (linked)
- REGISTER (linked)
- UPDATE (linked)
- RENEW (linked)
- TRANSFER (linked)
- FINALIZE (linked)
These are tied to the height after the coin got mined.
- Name/Coin has expired (burned)
- BID got burned (unrevealable)
- Add ability to send coinview with block data from chain to the wallet.
- Add block height hooks, for expires and lost bids.
- Track name expires.
- Track lost bids.
- For newly discovered names(missed reveals), emit event to rescan the auction to find the winner.
- Fix bid/reveal listings for reopened auctions (older ones show up again).
- Spendable balance
- Spendable balance (unconfirmed)
- Burned coins (that no longer can be unlocked) - Values burned in names. - Values burned in unrevealable bids. (lost?)
- Burned coins unconfirmed - Values burned in names.
- Active locked balance (w/o burned)
- Actice unconfirmed balance (w/o burned)
spent credits
- Coins that are ours, but are tagged as spent.spent coins
- Basically already removed from the list of coins we track.