ZMQ: add publishers for wallet transactions. #10554

pull somdoron wants to merge 2 commits into bitcoin:master from somdoron:zmq_wallet_tx changing 12 files +138 −8
  1. somdoron commented at 1:21 pm on June 8, 2017: none

    There is no way to only get real time notifications of transaction that affect the wallet. You have to do that manually by enabling zmqrawtx and filter out transactions.

    I’m suggesting adding two new publisers, both for hash and raw wallet transactions.

    Also topic will indicate if transaction came from mempool or block so developers can handle the transaction accordingly without a RPC round trip to bitcoind.

    Tests and documentation are updated.

  2. fanquake added the label RPC/REST/ZMQ on Jun 8, 2017
  3. in src/validationinterface.h:57 in 76d3e3bb9e outdated
    52@@ -52,6 +53,8 @@ struct CMainSignals {
    53     boost::signals2::signal<void (const CBlockIndex *, const CBlockIndex *, bool fInitialDownload)> UpdatedBlockTip;
    54     /** Notifies listeners of a transaction having been added to mempool. */
    55     boost::signals2::signal<void (const CTransactionRef &)> TransactionAddedToMempool;
    56+    /** Notifies listeners of a transaction having been added to the wallet. */
    57+    boost::signals2::signal<void (const CTransactionRef &, uint256 hashBlock)> TransactionAddedWallet;
    


    ryanofsky commented at 2:19 pm on June 8, 2017:
    Probably s/TransactionAddedWallet/TransactionAddedToWallet/ for consistency

    ryanofsky commented at 2:20 pm on June 8, 2017:
    Throughout the PR, should use const uint256& instead of uint256 arg type to avoid unnecessary copies.
  4. in doc/zmq.md:80 in 76d3e3bb9e outdated
    76@@ -75,6 +77,11 @@ notification `-zmqpubhashtx` the topic is `hashtx` (no null
    77 terminator) and the body is the hexadecimal transaction hash (32
    78 bytes).
    79 
    80+For wallet transaction notifications (both hash and tx), the topic also indicate if the transaction came from a block or mempool.
    


    ryanofsky commented at 2:21 pm on June 8, 2017:
    Maybe wrap these lines for consistency with rest of the file.
  5. ryanofsky commented at 2:31 pm on June 8, 2017: member
    utACK 76d3e3bb9e2d5fd5e0c570489cc377ce95cc370f. Change looks good. Left some minor comments.
  6. laanwj commented at 2:41 pm on June 8, 2017: member

    Concept ACK - however some comments:

    • This should respect ENABLE_WALLET, for compiling without wallet support
    • It should respect runtime -wallet=0
    • Wallet events should not go through CValidationInterface, it is for validation events only. To do this correctly, zmq should subscribe to wallet events through CWallet directly.
  7. somdoron force-pushed on Jun 8, 2017
  8. somdoron commented at 11:05 pm on June 8, 2017: none
    @ryanofsky fixed the type, wrapped the docs and using const uint256 &hashBlock @laanwj using wallet directly (without going through CValidationInterface) and respecting ENABLE_WALLET. Respecting -wallet=0 by checking if pwalletMain is not null.
  9. somdoron force-pushed on Jun 10, 2017
  10. somdoron force-pushed on Jun 10, 2017
  11. somdoron force-pushed on Jun 10, 2017
  12. somdoron force-pushed on Jun 10, 2017
  13. somdoron commented at 8:39 pm on June 10, 2017: none
    @ryanofsky @laanwj rebased the pull request on top of @jnewbery pull request #10555 and now all tests are passing
  14. sipa commented at 10:52 pm on June 12, 2017: member
    Does ZMQ have any authentication? I believe originally nothing wallet-related was exposed through it, as there may at least by privacy issues from publishing this.
  15. somdoron commented at 6:41 am on June 13, 2017: none

    zeromq does have authentication, but it is not being used within bitcoind. Do you think it is needed here? my only counter argument is that it should be exposed to internal network and trusted peers only.

    But if you feel that it is needed I can add authentication for the wallet publishers.

  16. laanwj commented at 7:17 am on June 13, 2017: member

    Do you think it is needed here? my only counter argument is that it should be exposed to internal network and trusted peers only.

    We could just add a warning (to the option help enabling this) that the API is unauthenticated, and thus wallet notifications should not be used when the zmq endpoints are accessible to other users - they can be restricted by other means, e.g. binding locally, binding to UNIX socket, firewall, etc.

    But if you feel that it is needed I can add authentication for the wallet publishers.

    I’d insist on that only when adding control of the wallet to the ZMQ interface.

  17. sipa commented at 8:16 am on June 13, 2017: member
    I have no strong opinion on the need for authentication; I just wanted to bring up that I believed that was the reason for not having wallet specific notifications in ZMQ before.
  18. MarcoFalke commented at 12:27 pm on June 18, 2017: member
    Needs rebase.
  19. somdoron force-pushed on Jun 20, 2017
  20. somdoron commented at 5:31 pm on June 20, 2017: none
    @MarcoFalke rebased
  21. in src/zmq/zmqnotificationinterface.cpp:121 in 3c0050839a outdated
    115@@ -110,6 +116,12 @@ bool CZMQNotificationInterface::Initialize()
    116 void CZMQNotificationInterface::Shutdown()
    117 {
    118     LogPrint(BCLog::ZMQ, "zmq: Shutdown notification interface\n");
    119+
    120+#ifdef ENABLE_WALLET
    121+    if (pwalletMain)
    


    MarcoFalke commented at 5:52 pm on June 20, 2017:
    nit: missing braces { and } for the if block, also this need adjustment for multiwallet.

    somdoron commented at 7:44 pm on June 20, 2017:
    fixed both
  22. somdoron force-pushed on Jun 20, 2017
  23. somdoron commented at 8:14 pm on June 20, 2017: none
    @MarcoFalke fixed and rebased
  24. in src/wallet/wallet.h:1072 in 2c393441b8 outdated
    1068@@ -1069,6 +1069,9 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
    1069     boost::signals2::signal<void (CWallet *wallet, const uint256 &hashTx,
    1070             ChangeType status)> NotifyTransactionChanged;
    1071 
    1072+    boost::signals2::signal<void (const CTransactionRef &ptxn,
    


    ryanofsky commented at 4:17 pm on June 21, 2017:

    I think you should make this a static variable to make the zmq code simpler and less fragile and remove the dependency on ::vpwallets. Advantages of making this static:

    • It will let you get rid of the ConnectToWalletSignals method and all the ifdefed code around it and simply connect to the signal in CZMQNotificationInterface::Initialize consistent with you how currently disconnect in CZMQNotificationInterface::Shutdown
    • If will make it possible in the future for new wallets to be added to ::vpwallets at runtime without having to modify zmq code and make it register for new notifications.

    somdoron commented at 4:36 pm on June 21, 2017:
    thanks, will make the change
  25. ryanofsky commented at 4:28 pm on June 21, 2017: member

    utACK 2c393441b8dc55322625670a7aaf37e2df583e29, but I definitely think you should consider making CWallet::TransactionAddedToWallet static as described below to make init and shutdown less fragile.

    Changes since previous review were moving the signal from validation interface to wallet, passing txids by const reference, wrapping markdown documentation, rebasing the test.

  26. somdoron force-pushed on Jun 22, 2017
  27. in src/wallet/wallet.cpp:63 in 123c3e75e9 outdated
    55@@ -56,6 +56,12 @@ CFeeRate CWallet::minTxFee = CFeeRate(DEFAULT_TRANSACTION_MINFEE);
    56  * Override with -fallbackfee
    57  */
    58 CFeeRate CWallet::fallbackFee = CFeeRate(DEFAULT_FALLBACK_FEE);
    59+/*
    60+ * Signal when transactions are added to wallet
    61+ */
    62+boost::signals2::signal<void (const CTransactionRef &ptxn,
    63+const uint256 &blockHash)> CWallet::TransactionAddedToWallet = boost::signals2::signal<void (const CTransactionRef &ptxn,
    


    ryanofsky commented at 3:42 pm on June 22, 2017:
    You should be able to shorten this by getting rid of the assignment (it will just call the default constructor which is fine).

    somdoron commented at 4:41 pm on June 22, 2017:
    fixed and rebased last commit. Do you want me to rebase everything into one commit?

    ryanofsky commented at 4:50 pm on June 22, 2017:

    fixed and rebased last commit. Do you want me to rebase everything into one commit?

    No preference, either way seems fine.

  28. ryanofsky commented at 4:23 pm on June 22, 2017: member
    utACK 123c3e75e96e56a78387353d10dd05b8d73e51c1. Change since last review was a new commit making the wallet signal static.
  29. somdoron force-pushed on Jun 22, 2017
  30. somdoron force-pushed on Jun 22, 2017
  31. ryanofsky commented at 4:51 pm on June 22, 2017: member
    utACK d358230d10b00ef7e1a284d1b855fa1604bf1d28. Only change since last review was removing unneeded init assignment.
  32. in doc/zmq.md:87 in d358230d10 outdated
    82+or mempool. If originated from mempool `-mempool` postfix
    83+will be added to the topic, for block `-block` postfix will
    84+be added. Because zeromq is using prefix matching for topics
    85+you can subscribe to `rawwallettx` (or `hashwallettx`) to get
    86+both notifications. If you only want one type of notification
    87+subscribe to either `rawwallettx-mempool` or `rawwallettx-block`.
    


    luke-jr commented at 4:06 am on September 2, 2017:
    No documentation on how to determine which wallet this transaction involves (is it even possible?)

    somdoron commented at 6:04 am on September 3, 2017:
    It was actually submitted before the multi-wallet was merged. Wallet name (or identifier) can be part of the topic.
  33. in src/wallet/wallet.cpp:64 in d358230d10 outdated
    55@@ -56,6 +56,10 @@ CFeeRate CWallet::minTxFee = CFeeRate(DEFAULT_TRANSACTION_MINFEE);
    56  * Override with -fallbackfee
    57  */
    58 CFeeRate CWallet::fallbackFee = CFeeRate(DEFAULT_FALLBACK_FEE);
    59+/*
    60+ * Signal when transactions are added to wallet
    61+ */
    62+boost::signals2::signal<void (const CTransactionRef &ptxn, const uint256 &blockHash)> CWallet::TransactionAddedToWallet;
    


    luke-jr commented at 4:07 am on September 2, 2017:
    IMO blockHash should be nullptr when not in a block.

    luke-jr commented at 4:07 am on September 2, 2017:
    Probably CWalletTx should be passed instead of CTransactionRef?

    somdoron commented at 11:03 am on September 4, 2017:
    actually if CWalletTX is used the blockhash is not needed anymore. I will take a look.
  34. ryanofsky commented at 6:05 pm on October 12, 2017: member
    @somdoron are you still working on this? IIUC, luke’s improvements could be implemented later without breaking backwards compatibility, if they are what’s holding this up.
  35. somdoron commented at 8:12 am on October 17, 2017: none
    @ryanofsky yes, will rebase today and send a PR
  36. somdoron force-pushed on Oct 19, 2017
  37. ZMQ: add publishers of wallet tx
    There is no way to get real time notification of transactions that only affect the wallet.
    You have to do that manually by enabling zmqrawtx and filter out transactions.
    
    I'm suggesting adding two new publisers, both for hash and raw wallet transactions.
    
    Also topic will indicate if transaction came from mempool or block so developers can handle the transaction accordingly without a RPC round trip to bitcoind.
    d6448d40fc
  38. ZMQ: Making CWallet::TransactionAddedToWallet static
    In order to avoid the registration for wallet signals.
    Also enable dynamic addition of wallets without register them with ZMQ
    ed4fd266f7
  39. somdoron force-pushed on Oct 19, 2017
  40. somdoron commented at 5:38 am on October 22, 2017: none
    @ryanofsky rebased and all tests passed. Doesn’t yet include @luke-jr comments.
  41. in src/zmq/zmqpublishnotifier.cpp:177 in ed4fd266f7
    169@@ -166,6 +170,23 @@ bool CZMQPublishHashTransactionNotifier::NotifyTransaction(const CTransaction &t
    170     return SendMessage(MSG_HASHTX, data, 32);
    171 }
    172 
    173+bool CZMQPublishHashWalletTransactionNotifier::NotifyWalletTransaction(const CTransaction &transaction, const uint256 &hashBlock){
    174+    uint256 hash = transaction.GetHash();
    175+    LogPrint(BCLog::ZMQ, "zmq: Publish hashwallettx %s\n", hash.GetHex());
    176+    char data[32];
    177+    for (unsigned int i = 0; i < 32; i++)
    


    jonasschnelli commented at 1:22 am on October 23, 2017:
    memcpy?

    jonasschnelli commented at 1:24 am on October 23, 2017:
    Nevermind. I see we do reverse the byte order here…

    jnewbery commented at 2:04 pm on October 23, 2017:
    nit: braces please
  42. jonasschnelli commented at 1:26 am on October 23, 2017: contributor

    I’m still unsure about this, if wtxs (protected by http auth) should be something we broadcast via ZMQ. Alternative would be HTTP based long polling (#7949).

    Also, how does this handle multiwallet? Should we somehow integrate the wallet identifier in the notifications?

  43. in src/zmq/zmqnotificationinterface.cpp:14 in ed4fd266f7
     9@@ -10,6 +10,10 @@
    10 #include "streams.h"
    11 #include "util.h"
    12 
    13+#ifdef ENABLE_WALLET
    14+#include "../wallet/wallet.h"
    


    jnewbery commented at 1:57 pm on October 23, 2017:

    There only seem to be a couple of other relative includes in the codebase. Other files use:

    #include "wallet/wallet.h"

  44. in src/zmq/zmqnotificationinterface.cpp:205 in ed4fd266f7
    200+    const CTransaction& tx = *ptx;
    201+
    202+    for (std::list<CZMQAbstractNotifier*>::iterator i = notifiers.begin(); i!=notifiers.end(); )
    203+    {
    204+        CZMQAbstractNotifier *notifier = *i;
    205+        if (notifier->NotifyWalletTransaction(tx, hashBlock))
    


    jnewbery commented at 2:00 pm on October 23, 2017:
    style nit: braces on same line please.
  45. in src/zmq/zmqnotificationinterface.cpp:209 in ed4fd266f7
    204+        CZMQAbstractNotifier *notifier = *i;
    205+        if (notifier->NotifyWalletTransaction(tx, hashBlock))
    206+        {
    207+            i++;
    208+        }
    209+        else
    


    jnewbery commented at 2:00 pm on October 23, 2017:

    style nit:

    } else {

  46. in src/zmq/zmqpublishnotifier.cpp:182 in ed4fd266f7
    177+    for (unsigned int i = 0; i < 32; i++)
    178+        data[31 - i] = hash.begin()[i];
    179+
    180+    const char *command;
    181+
    182+    if (!hashBlock.IsNull())
    


    jnewbery commented at 2:04 pm on October 23, 2017:
    nit: braces please.
  47. in src/zmq/zmqabstractnotifier.cpp:24 in ed4fd266f7
    19@@ -20,3 +20,7 @@ bool CZMQAbstractNotifier::NotifyTransaction(const CTransaction &/*transaction*/
    20 {
    21     return true;
    22 }
    23+
    24+bool CZMQAbstractNotifier::NotifyWalletTransaction(const CTransaction &transaction, const uint256 &hashBlock){
    


    jnewbery commented at 2:13 pm on October 23, 2017:
    nit: function brace on newline please.
  48. in test/functional/zmq_test.py:26 in ed4fd266f7
    22@@ -22,16 +23,17 @@ def __init__(self, socket, topic):
    23         import zmq
    24         self.socket.setsockopt(zmq.SUBSCRIBE, self.topic)
    25 
    26-    def receive(self):
    27+    def receive(self, specific_topic = None):
    


    jnewbery commented at 2:35 pm on October 23, 2017:
    nit: no spaces around the = for named arguments.
  49. in test/functional/test_framework/util.py:40 in ed4fd266f7
    36@@ -37,6 +37,10 @@ def assert_equal(thing1, thing2, *args):
    37     if thing1 != thing2 or any(thing1 != arg for arg in args):
    38         raise AssertionError("not(%s)" % " == ".join(str(arg) for arg in (thing1, thing2) + args))
    39 
    40+def assert_not_equal(thing1, thing2):
    


    jnewbery commented at 2:52 pm on October 23, 2017:
    You’ve added this but not used it. If it’s not being used, can you remove it from this PR?
  50. jnewbery commented at 2:58 pm on October 23, 2017: member

    Apologies for all the style nits. Please see https://github.com/bitcoin/bitcoin/blob/6157e8ce3937af3f46d3e7dd922d19d6dc272145/doc/developer-notes.md for the full style guide.

    I agree with the other reviewers that this needs a bit more work for multiwallet. Can you either:

    1. add documentation saying that multiwallet is supported but that notifications will not indicate which wallet the notification is for; or
    2. add the wallet name to the notification topic

    Both are fine. You could do (1) now and a future PR could add the name of the wallet to the notification.

    Can you also update the zmq_test.py to verify that this notifications are received for all wallets when multiwallet is being used? I have a branch here that does that: https://github.com/jnewbery/bitcoin/tree/pr10554.1 . Feel free to take that and squash into your commit if you like it.

    Also, I think this could use some extra documentation warning users about security implications:

    • zmq is unauthenticated
    • notifications are received for all wallets and can’t be enabled/disabled on a per-wallet basis.
  51. ryanofsky commented at 8:04 pm on October 31, 2017: member
    utACK ed4fd266f78f9fea8dd0e4cb94553e55171fb7d2. Only change since last review is rebase. Agree with John it’d be good to document the multiwallet limitation if you don’t want to add wallet names to the notifications right now. Also I don’t see any reason not to squash the two commits. Would make understanding the PR a little simpler.
  52. luke-jr referenced this in commit e26209d0ba on Nov 6, 2017
  53. ryanofsky commented at 8:20 pm on January 9, 2018: member
    For some reason travis is failing with contrib/devtools/lint-python.sh: 10: contrib/devtools/lint-python.sh: flake8: not found. It’s possible a rebase might fix this.
  54. promag commented at 3:51 pm on January 10, 2018: member

    Alternative would be HTTP based long polling (#7949).

    I tend to agree with @jonasschnelli alternative.

  55. breitsmiley commented at 9:35 pm on May 4, 2018: none
    What about this PR? Is it going to be added?
  56. jnewbery commented at 9:44 pm on May 4, 2018: member

    No update from PR author @somdoron since October 2017. Are you still working on this @somdoron ?

    If not, I suggest we close this as ‘Up for grabs’

  57. somdoron commented at 6:16 am on May 5, 2018: none

    You can close.

    I actually used the code in production as part of payments solution.

  58. jnewbery closed this on May 5, 2018

  59. jnewbery added the label Up for grabs on May 5, 2018
  60. MarcoFalke locked this on Sep 8, 2021

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-07-03 13:13 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me