[Wallet] Refactoring by using CInputCoin instead of std::pair #10165

pull NicolasDorier wants to merge 4 commits into bitcoin:master from NicolasDorier:inputcoin changing 5 files +71 −47
  1. NicolasDorier commented at 10:10 AM on April 7, 2017: contributor

    The code was using std::pair<const CWalletTx*, unsigned int> until now. Not only it is ugly to read, and easy to mess up, but it needlessly pass CWalletTx all around the code when it is not needed.

    This code will simplify another PR extending FundRawTransaction. (https://github.com/bitcoin/bitcoin/pull/10068)

    This is divided in 3 commits easy to review.

    1. Just rename std::pair<const CWalletTx*, unsigned int> to CInputCoin by using a type alias
    2. Transform CInputCoin into a class.
    3. Rewrite some code which can be simplified thanks to CInputCoin
  2. NicolasDorier force-pushed on Apr 7, 2017
  3. NicolasDorier force-pushed on Apr 7, 2017
  4. laanwj added the label Wallet on Apr 7, 2017
  5. in src/wallet/wallet.h:485 in 8227fcc0ba outdated
     481 | +    CInputCoin()
    
     482 | +    {
    
     483 | +    }
    
     484 | +    CInputCoin(const CWalletTx* walletTx, unsigned int i)
    
     485 | +    {
    
     486 | +        if (walletTx != nullptr && i < walletTx->tx->vout.size())
    
    


    ryanofsky commented at 12:39 PM on April 7, 2017:

    Would suggest throwing std::out_of_range if this condition is not true. This should be compatible with all the places this code is called (since they previously would have resulted in out-of-bounds memory accesses).


    laanwj commented at 4:26 PM on April 7, 2017:

    I agree. That's safer than leaving the object as invalid dummy object, which would be harder to troubleshoot as it's not checked against everywhere..

  6. in src/wallet/wallet.h:480 in 8227fcc0ba outdated
     474 | @@ -475,7 +475,38 @@ class CWalletTx : public CMerkleTx
     475 |  };
     476 |  
     477 |  
     478 | -using CInputCoin = std::pair<const CWalletTx*, unsigned int>;
     479 | +class CInputCoin {
    
     480 | +public:
    
     481 | +    CInputCoin()
    
    


    ryanofsky commented at 1:04 PM on April 7, 2017:

    Would suggest deleting default constructor and IsNull method. Their presence seem to make this class more complex and precarious than is necessary, and could lead to bugs and unintended behavior.

    The only place where a nullable CInputCoin seems to be used is in one coinLowestLarger local variable, and you could more easily declare this variable as boost::optional<CInputCoin> coinLowestLarger; (or std::optional in the future) instead of building in a layer of optionality into the type.


    NicolasDorier commented at 2:20 PM on April 7, 2017:

    I don't think using optional would make the code more clear. I never saw it used anywhere in bitcoin. What about using CInputCoin* for coinLowestLarger instead?


    ryanofsky commented at 2:44 PM on April 7, 2017:

    I don't think using optional would make the code more clear.

    I think optional's useful. It saves work of having to build optionality into types you define, and more importantly it allows the same type to be optional in some contexts and required in others, which I think is exactly what you want here. std::optional is part of c++17 so eventually it will start becoming more commonly used.

    Anyway, this was just a suggestion, so feel free to ignore it if you have a different preference.

    What about using CInputCoin* for coinLowestLarger instead?

    Using a pointer was actually going to be my first suggestion, but I didn't see a way to make that work because coinLowestLarger is assigned from a local variable. But I think this would be an improvement if it could work.

  7. ryanofsky commented at 1:08 PM on April 7, 2017: member

    utACK 2f5eb873dda9d1561c233a2313322a53afea5161, nice cleanup

  8. [Wallet] Rename std::pair<const CWalletTx*, unsigned int> to CInputCoin fd44ac1e8b
  9. NicolasDorier force-pushed on Apr 8, 2017
  10. NicolasDorier commented at 3:54 AM on April 8, 2017: contributor

    I needed to rebase, I ended up using boost::optional and getting ride of IsNull() + added checks for inconsistency in the constructor. @ryanofsky @laanwj can you reACK?

  11. btcdrak commented at 8:03 PM on April 9, 2017: contributor

    utACK 7e0b365

  12. laanwj commented at 12:07 PM on April 10, 2017: member

    I needed to rebase, I ended up using boost::optional

    Was about to ask "why not std::optional" but apparently that's C++17. Well, easy to replace when we adapt that - the concept is great.

  13. in src/wallet/wallet.h:478 in fd44ac1e8b outdated
     474 | @@ -475,7 +475,7 @@ class CWalletTx : public CMerkleTx
     475 |  };
     476 |  
     477 |  
     478 | -
     479 | +using CInputCoin = std::pair<const CWalletTx*, unsigned int>;
    


    JeremyRubin commented at 3:24 PM on April 10, 2017:

    Prefer to use a typedef (I actually prefer using personally, but some devs are unfamiliar with it and you don't need it as CInputCoin is not templated)

    Also, prefer a non-Hungarian name if you're introducing a new class. See #9472 (review) -- Hungarians for new code discouraged.

  14. in src/wallet/wallet.cpp:2122 in da0d2aaafa outdated
    2125 |              vValue.push_back(coin);
    2126 | -            nTotalLower += n;
    2127 | +            nTotalLower += coin.txout.nValue;
    2128 |          }
    2129 | -        else if (n < coinLowestLarger.first)
    2130 | +        else if (coinLowestLarger.IsNull() || coin.txout.nValue < coinLowestLarger.txout.nValue)
    


    JeremyRubin commented at 3:33 PM on April 10, 2017:

    I'm a bit confused here -- isn't coinLowestLarger always null at this point?

  15. in src/wallet/wallet.h:495 in ba540965ed outdated
     491 | +    }
    
     492 | +    bool IsNull() const
    
     493 | +    {
    
     494 | +        return outpoint.IsNull() && txout.IsNull();
    
     495 | +    }
    
     496 | +    COutPoint outpoint;
    
    


    JeremyRubin commented at 3:35 PM on April 10, 2017:

    prefer not to have fields intermixed with functions.

  16. in src/wallet/wallet.h:484 in 7e0b36583d outdated
     483 |      CInputCoin(const CWalletTx* walletTx, unsigned int i)
     484 |      {
     485 | -        if (walletTx != nullptr && i < walletTx->tx->vout.size())
    
     486 | +        if (walletTx == nullptr)
    
     487 | +            throw std::invalid_argument("walletTx should not be null");
    
     488 | +        if (i < walletTx->tx->vout.size())
    
    


    JeremyRubin commented at 3:41 PM on April 10, 2017:

    Can you invert the logic here if (!P) throw is a bit easier to read.

    Might also be good to make it a const CWalletTx& so as to make sure that de-referencability is checked everywhere that this is called.


    NicolasDorier commented at 10:32 AM on April 11, 2017:

    Ah indeed, C# habits... Just replaced by if(!walletTx).

    I would like to do const CWalletTx& in a separate PR, as it need more code change, and I need this PR for another one depending on it.


    JeremyRubin commented at 6:52 PM on April 11, 2017:

    Ah, I was unclear -- I actually don't mind a == nullptr (although current state is cleaner), I was referring to the throw out_of_range. It's easier if a constructor is: if (! preconditionA) throw A; if (!preconditionB) throw B; ....; rather than if (! preconditionA) throw A; if (preconditionB)...; else throw B;


    NicolasDorier commented at 2:36 AM on April 12, 2017:

    @JeremyRubin indeed, much clearer. I updated the PR.

  17. JeremyRubin commented at 3:41 PM on April 10, 2017: contributor

    Couple nits/questions (be sure to show outdated) but overall Concept Ack.

  18. in src/wallet/wallet.h:492 in 7e0b36583d outdated
     492 | +            throw std::out_of_range("The output index is out of range");
    
     493 | +        }
    
     494 | +    }
    
     495 | +
    
     496 | +    COutPoint outpoint;
    
     497 | +    CTxOut txout;
    
    


    bulldozer00 commented at 4:26 PM on April 10, 2017:

    Why are these data members public and not private?


    NicolasDorier commented at 10:23 AM on April 11, 2017:

    because I use them outside the class.

  19. in src/wallet/test/wallet_tests.cpp:32 in 7e0b36583d outdated
      28 | @@ -29,7 +29,7 @@ extern UniValue importmulti(const JSONRPCRequest& request);
      29 |  
      30 |  std::vector<std::unique_ptr<CWalletTx>> wtxn;
      31 |  
      32 | -typedef std::set<std::pair<const CWalletTx*,unsigned int> > CoinSet;
      33 | +typedef std::set<CInputCoin> CoinSet;
    


    bulldozer00 commented at 4:28 PM on April 10, 2017:

    Think about replacing old style "typedef X Y " with the more intuitive C++11 "using Y = X" style


    NicolasDorier commented at 10:23 AM on April 11, 2017:

    better to do in a separate PR. I want to keep it focused on CInputCoin.


    laanwj commented at 3:16 PM on April 12, 2017:

    We don't use that style anywhere, introducing it here is not a good idea. I'd prefer to save that for new code.

  20. NicolasDorier force-pushed on Apr 11, 2017
  21. NicolasDorier force-pushed on Apr 12, 2017
  22. NicolasDorier commented at 6:14 AM on April 12, 2017: contributor

    Travis fail unrelated to this PR, @laanwj can you kick the travis box one time to fix the issue ?

  23. [Wallet] Decouple CInputCoin from CWalletTx e78bc45810
  24. [Wallet] Simplify code using CInputCoin f597dcb7c8
  25. [Wallet] Prevent CInputCoin to be in a null state c37e32af0d
  26. in src/wallet/wallet.h:478 in bffa5e5969 outdated
     474 | @@ -475,7 +475,34 @@ class CWalletTx : public CMerkleTx
     475 |  };
     476 |  
     477 |  
     478 | -
     479 | +class CInputCoin {
    
    


    laanwj commented at 3:37 PM on April 12, 2017:

    It is not visible on github but local diff shows me that line endings are weird here:

    -using CInputCoin = std::pair<const CWalletTx*, unsigned int>;
    +class CInputCoin {^M
    +public:^M
    

    ^M is 13, so I suppose these are DOS line endings. Looks like it is only in src/wallet/wallet.h, and only the newly introduced code. suggest running:

    $ dos2unix src/wallet/wallet.h
    dos2unix: converting file src/wallet/wallet.h to Unix format ...
    

    NicolasDorier commented at 5:33 AM on April 13, 2017:

    oops. Yes, developping on visual studio... Fixed.

  27. NicolasDorier force-pushed on Apr 13, 2017
  28. laanwj merged this on Apr 13, 2017
  29. laanwj closed this on Apr 13, 2017

  30. laanwj referenced this in commit 70f6f56e9d on Apr 13, 2017
  31. PastaPastaPasta referenced this in commit 96b6b6f039 on May 31, 2019
  32. PastaPastaPasta referenced this in commit 7b86d3a318 on May 31, 2019
  33. PastaPastaPasta referenced this in commit 4b02fb8193 on May 31, 2019
  34. PastaPastaPasta referenced this in commit 21635373cf on Jun 10, 2019
  35. PastaPastaPasta referenced this in commit 1d855a9a04 on Jun 10, 2019
  36. PastaPastaPasta referenced this in commit 35d0f47ef5 on Jun 11, 2019
  37. PastaPastaPasta referenced this in commit c13da860ef on Jun 11, 2019
  38. PastaPastaPasta referenced this in commit 39f577f70d on Jun 12, 2019
  39. PastaPastaPasta referenced this in commit 69b42ce671 on Jun 14, 2019
  40. PastaPastaPasta referenced this in commit 635287384f on Jun 15, 2019
  41. PastaPastaPasta referenced this in commit 1af86a839e on Jun 19, 2019
  42. barrystyle referenced this in commit 370c3671d2 on Jan 22, 2020
  43. 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: 2026-04-13 15:15 UTC

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