Skip to content

Conversation

@kallewoof
Copy link
Contributor

@kallewoof kallewoof commented Jan 24, 2017

The following scenario will not notify the caller of the fact tx0 has been dropped:

  1. User 1 receives BTC in tx0 from utxo1 in block aa1.
  2. User 2 receives BTC in tx1 from utxo1 (same) in block bb1
  3. User 1 sees 2 confirmations at block aa3.
  4. Reorg into bb chain.
  5. User 1 asks listsinceblock aa3 and does not see that tx0 is now invalidated.

See listsinceblock.py commit for related test.

The proposed fix is to iterate from the given block down to the fork point, and to check each transaction in the blocks against the wallet, in addition to including all transactions from the fork point to the active chain tip (the current behavior). Any transactions that were present will now also be listed in the listsinceblock output in a new replaced array. This operation may be a bit heavy but the circumstances (and perceived frequency of occurrence) warrant it, I believe.

Example output:

{
  'transactions': [],
  'replaced': [
    {
      'walletconflicts': [],
      'vout': 1,
      'account': '',
      'timereceived': 1485234857,
      'time': 1485234857,
      'amount': '1.00000000',
      'bip125-replaceable': 'unknown',
      'trusted': False,
      'category': 'receive',
      'txid': 'ce673859a30dee1d2ebdb3c05f2eea7b1da54baf68f93bb8bfe37c5f09ed22ff',
      'address': 'miqEt4kWp9zSizwGGuUWLAmxEcTW9bFUnQ',
      'label': '',
      'confirmations': -7
    }
  ],
  'lastblock': '7a388f27d09e3699102a4ebf81597d974fc4c72093eeaa02adffbbf7527f6715'
}

I believe this addresses the comment by @luke-jr in #9516 (comment) but I could be wrong..

@jonasschnelli
Copy link
Contributor

I'm not 100% sure if we want this. If we, we would need at least to updated the listsinceblock's RPC help message to mention that if one requests tx's from a block outside the main-chain, that the result will also contain transactions not in the main chain.

@kallewoof
Copy link
Contributor Author

kallewoof commented Jan 24, 2017

@jonasschnelli Updated the help output. I am not sure what the reasons for not wanting this are, unless you're referring to resource consumption. I think it's a rare (but important) enough case to warrant it.

It would definitely make it easier for RPC applications checking the validity of existing transactions to explicitly provide these when a reorg affects them. The only other alternative right now is to keep a list of transactions with confirmations less than some arbitrary number (100) and to loop through these every time a reorg is encountered to ensure they're actually still present.

Edit: one concern of my own is whether a naive implementation would ignore the confirmations value and simply think the transaction existed in the chain, even though the opposite is the case. I wondered if maybe a different key for the returned results should be used, e.g. "reorged" or something. I.e. you would get {"transactions": [list of txs that changed], "reorged": [list of txs that disappeared], "lastblock": <hash>}...

@jonasschnelli
Copy link
Contributor

@kallewoof: I missed the point that if you pass in an orphan block to list since, you also get the transactions upwards the chain-fork on the main chain. At first sight, I though you get only tx from the re-orged-off chain in that case.

Concept ACK (and I think it would be clever to list them in an extra array element reorged:[].

@kallewoof
Copy link
Contributor Author

@jonasschnelli Gotcha. I updated the OP to clarify that it's also including transactions from the fork point to the active chain tip. I also moved the off chain transactions into a new 'reorged' array. (f501acc & 461d5a3)

Copy link
Contributor

@ryanofsky ryanofsky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK 461d5a37a3d83edbeedb701ed207bc14412dee0d with minor suggestions

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be helpful to add a comment about -depth here. I was staring at this a long time to figure out how it worked. Comment could say: "Pass -depth as minDepth to prevent any filtering in ListTransactions. (Works because tx can only conflict with transactions after pindex, so GetDepthInMainChain will always return at least (1-depth))."

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would s/back to the fork point/from blockhash back to the fork point/ to clarify, because it sounds to me like this is referring to transactions between the active tip and the fork point (making the rest of the sentence confusing).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need documentation update to accompany this.

Copy link
Contributor

@ryanofsky ryanofsky Jan 24, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really sending from node 1 here (even if key originally comes from node 2)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unused variable

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe condense this block to a single line, and add a check for txid2 (untested)

assert_equal(any(tx['txid'] == txid1 for tx in lsbres['reorged']), True)
assert_equal(any(tx['txid'] == txid2 for tx in lsbres['transactions']), True)

Copy link
Contributor Author

@kallewoof kallewoof Jan 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ryanofsky Ahh, nice! I didn't know about any().

Since txid2 is not related to nodes[0], it will not list it anywhere so that second assert_equal will not be true.

Thanks for all the feedback! I believe everything you suggested is in 9caa0ec & 131df5a.

@kallewoof kallewoof force-pushed the listsinceblock-include-lost-txs branch 2 times, most recently from 4faf084 to 131df5a Compare January 25, 2017 04:59
@maflcko maflcko added this to the 0.14.0 milestone Jan 25, 2017
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe change tx0 and tx1 to tx1 and tx2 to match code. Also code is generating 6 and 7 blocks instead of 3 and 4, so maybe that could be changed to match the example.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would remove parentheses since (at minimum -depth) is the important part. Also, technically I believe the minimum is 1-depth. Maybe:

// Use -depth as minDepth parameter to ListTransactions to prevent incoming
// transactions from being filtered. These transactions have negative
// confirmations, but always greater than -depth.

@kallewoof
Copy link
Contributor Author

@ryanofsky Thanks for all the feedback! Updated.

@gmaxwell
Copy link
Contributor

Concept ACK.

@kallewoof kallewoof force-pushed the listsinceblock-include-lost-txs branch from e66a1b1 to d92496c Compare January 27, 2017 12:30
Copy link
Contributor

@TheBlueMatt TheBlueMatt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I'd call this a bugfix - we already correctly print transactions which were included in blocks from the common fork point from the blockhash provided to listsinceblock.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont believe this prevents listing transactions which were on both sides of the fork? I'm pretty sure we dont want to list such transactions in a "reorged" list.

@kallewoof
Copy link
Contributor Author

@TheBlueMatt I guess it comes down to what the user expects. I personally expected listsinceblock to show me anything I needed to keep an updated score of what's going on since the given block. In that sense, not showing a transaction vanishing would probably be considered a bug.

Regarding showing an existing transaction in both reorged and transactions, I patched this by ensuring that any tx shown from the main chain is skipped over in the reorged list. See the new test_double_send test.

@kallewoof kallewoof force-pushed the listsinceblock-include-lost-txs branch from 544e77a to 7dcfa98 Compare January 30, 2017 03:02
@JeremyRubin
Copy link
Contributor

I agree with Matt, this isn't a bugfix, it's feature :)

I think I'm in favor of adding this. I would be more supportive of naming them replaced rather than reorged if I understand the semantics properly. Strictly speaking, I'd say a reorged txn is any transaction that was between the old tip and the fork point?

I would also think maybe making this information available with a default false parameter may be a good idea to introduce less changes for current users/legacy code.

@kallewoof kallewoof changed the title [rpc] Bug-fix: listsinceblock should include lost transactions when parameter is a reorg'd block [rpc] listsinceblock should include lost transactions when parameter is a reorg'd block Jan 30, 2017
@kallewoof
Copy link
Contributor Author

@JeremyRubin Changed as you said, except setting default of include_replaced to true as I think that will be the most useful case.

@kallewoof kallewoof force-pushed the listsinceblock-include-lost-txs branch 6 times, most recently from a157931 to 31654ae Compare January 30, 2017 11:00
@laanwj laanwj modified the milestones: 0.15.0, 0.14.0 Jan 30, 2017
@laanwj
Copy link
Member

laanwj commented Jan 30, 2017

Moving milestone to 0.15 as this was re-classified as a feature and the feature freeze is long past.

luke-jr pushed a commit to bitcoinknots/bitcoin that referenced this pull request Jun 18, 2017
…ected since the given block, including transactions that were removed due to a reorg.

Github-Pull: bitcoin#9622
Rebased-From: ef3db3bdd14329719a65c1ccb6cf6440678327c8
@sipa
Copy link
Member

sipa commented Jul 12, 2017

utACK 5d352044ca7f29f992b4de46d461bccc86326ba1 with a few nits. I did not review the tests.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: the request.params.size() > 0 check is superfluous with this, as the operator[] will always return a null UniValue if out of range. (and several other places)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I didn't know that. That makes things cleaner, thanks.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: braces on the same line (and many other places).

CBlock block;
if (!ReadBlockFromDisk(block, paltindex, Params().GetConsensus()))
{
throw JSONRPCError(RPC_INTERNAL_ERROR, "Can't read block from disk");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with (1), and not having allow_partial. We may want to document that this feature stops working with pruning.

@kallewoof kallewoof force-pushed the listsinceblock-include-lost-txs branch from 5d35204 to 0d457c7 Compare July 13, 2017 01:34
@kallewoof
Copy link
Contributor Author

@sipa Thanks for the review. I've addressed your nits in kallewoof@3a10e7c

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, technically -depth isnt sufficient here. In the rare case of a reorg-to-lower-block-height this would be insufficient. You already got the block from the chain, just call it - 1000000000 or so.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add something to note that transactions which were re-added are included here anyway, and may have, at that point, positive confirmations value in this array?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is wrong (and the check and later comment contradict this).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you duplicate this loop for "removed", noting that the tx listed in "removed" should also have a confirmations of 2.

@kallewoof kallewoof force-pushed the listsinceblock-include-lost-txs branch from 0d457c7 to d6115c2 Compare July 18, 2017 04:33
@kallewoof
Copy link
Contributor Author

@TheBlueMatt Thanks for the review! I've addressed all of your nits, I believe. The unsquashed changes are in kallewoof@5166d0e and kallewoof@299c00c.

@TheBlueMatt
Copy link
Contributor

I think this maybe missed 15, sadly. Its a nice change, but not a bugfix.

@kallewoof
Copy link
Contributor Author

That's disheartening, but ah well.

@TheBlueMatt
Copy link
Contributor

utACK d6115c21a790e139bb45ec6dee421a976bc21eaf. Yea, Core has been in a near-constant state of growing pains for some time it seems. Recently its grown active enough to be just beyond the ability of any individual to keep up with everything, and so things occasionally move slower than they should :(. Anyway, up to @laanwj, this isnt a bugfix, but its pretty clean so maybe he's still willing to pull it for 15.

@kallewoof
Copy link
Contributor Author

I'd say let's just push it to 16 milestone. I'll be noisy about it this time. :)

@TheBlueMatt
Copy link
Contributor

TheBlueMatt commented Jul 19, 2017 via email

@laanwj
Copy link
Member

laanwj commented Jul 20, 2017

Needs rebase.

I'd say let's just push it to 16 milestone. I'll be noisy about it this time. :)

Up to you, though given how long this has been open and how much interest and review this has I don't have a particular problem with merging this into 0.15 still.

…ndone due to reorg when requesting a non-main chain block in a new 'removed' array.
…ected since the given block, including transactions that were removed due to a reorg.
@kallewoof kallewoof force-pushed the listsinceblock-include-lost-txs branch from d6115c2 to 876e92b Compare July 21, 2017 00:51
@kallewoof
Copy link
Contributor Author

@laanwj Rebased. And I'd love to have this in 15, personally. I just don't wanna rush anything for the sake of the PR being old.

@sipa
Copy link
Member

sipa commented Jul 21, 2017

utACK

@laanwj laanwj merged commit 876e92b into bitcoin:master Jul 24, 2017
laanwj added a commit that referenced this pull request Jul 24, 2017
…en parameter is a reorg'd block

876e92b Testing: listsinceblock should display all transactions that were affected since the given block, including transactions that were removed due to a reorg. (Karl-Johan Alm)
f999c46 listsinceblock: optionally find and list any transactions that were undone due to reorg when requesting a non-main chain block in a new 'removed' array. (Karl-Johan Alm)

Pull request description:

  The following scenario will not notify the caller of the fact `tx0` has been dropped:

  1. User 1 receives BTC in tx0 from utxo1 in block aa1.
  2. User 2 receives BTC in tx1 from utxo1 (same) in block bb1
  3. User 1 sees 2 confirmations at block aa3.
  4. Reorg into bb chain.
  5. User 1 asks `listsinceblock aa3` and does not see that tx0 is now invalidated.

  See `listsinceblock.py` commit for related test.

  The proposed fix is to iterate from the given block down to the fork point, and to check each transaction in the blocks against the wallet, in addition to including all transactions from the fork point to the active chain tip (the current behavior). Any transactions that were present will now also be listed in the `listsinceblock` output in a new `replaced` array. This operation may be a bit heavy but the circumstances (and perceived frequency of occurrence) warrant it, I believe.

  Example output:
  ```Python
  {
    'transactions': [],
    'replaced': [
      {
        'walletconflicts': [],
        'vout': 1,
        'account': '',
        'timereceived': 1485234857,
        'time': 1485234857,
        'amount': '1.00000000',
        'bip125-replaceable': 'unknown',
        'trusted': False,
        'category': 'receive',
        'txid': 'ce673859a30dee1d2ebdb3c05f2eea7b1da54baf68f93bb8bfe37c5f09ed22ff',
        'address': 'miqEt4kWp9zSizwGGuUWLAmxEcTW9bFUnQ',
        'label': '',
        'confirmations': -7
      }
    ],
    'lastblock': '7a388f27d09e3699102a4ebf81597d974fc4c72093eeaa02adffbbf7527f6715'
  }
  ```

  I believe this addresses the comment by @luke-jr in #9516 (comment) but I could be wrong..

Tree-SHA512: 607b5dcaeccb9dc0d963d3de138c40490f3e923050b29821e6bd513d26beb587bddc748fbb194503fe618cfe34a6ed65d95e8d9c5764a882b6c5f976520cff35
@kallewoof kallewoof deleted the listsinceblock-include-lost-txs branch July 24, 2017 11:17
PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Aug 12, 2019
…ions when parameter is a reorg'd block

876e92b Testing: listsinceblock should display all transactions that were affected since the given block, including transactions that were removed due to a reorg. (Karl-Johan Alm)
f999c46 listsinceblock: optionally find and list any transactions that were undone due to reorg when requesting a non-main chain block in a new 'removed' array. (Karl-Johan Alm)

Pull request description:

  The following scenario will not notify the caller of the fact `tx0` has been dropped:

  1. User 1 receives BTC in tx0 from utxo1 in block aa1.
  2. User 2 receives BTC in tx1 from utxo1 (same) in block bb1
  3. User 1 sees 2 confirmations at block aa3.
  4. Reorg into bb chain.
  5. User 1 asks `listsinceblock aa3` and does not see that tx0 is now invalidated.

  See `listsinceblock.py` commit for related test.

  The proposed fix is to iterate from the given block down to the fork point, and to check each transaction in the blocks against the wallet, in addition to including all transactions from the fork point to the active chain tip (the current behavior). Any transactions that were present will now also be listed in the `listsinceblock` output in a new `replaced` array. This operation may be a bit heavy but the circumstances (and perceived frequency of occurrence) warrant it, I believe.

  Example output:
  ```Python
  {
    'transactions': [],
    'replaced': [
      {
        'walletconflicts': [],
        'vout': 1,
        'account': '',
        'timereceived': 1485234857,
        'time': 1485234857,
        'amount': '1.00000000',
        'bip125-replaceable': 'unknown',
        'trusted': False,
        'category': 'receive',
        'txid': 'ce673859a30dee1d2ebdb3c05f2eea7b1da54baf68f93bb8bfe37c5f09ed22ff',
        'address': 'miqEt4kWp9zSizwGGuUWLAmxEcTW9bFUnQ',
        'label': '',
        'confirmations': -7
      }
    ],
    'lastblock': '7a388f27d09e3699102a4ebf81597d974fc4c72093eeaa02adffbbf7527f6715'
  }
  ```

  I believe this addresses the comment by @luke-jr in bitcoin#9516 (comment) but I could be wrong..

Tree-SHA512: 607b5dcaeccb9dc0d963d3de138c40490f3e923050b29821e6bd513d26beb587bddc748fbb194503fe618cfe34a6ed65d95e8d9c5764a882b6c5f976520cff35
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Sep 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.