Skip to content

Conversation

jonasschnelli
Copy link
Contributor

This will allow a upcomming modularization of the wallet or other components.
Currently there is no use of the flexible RPC dispatch table.

Because #5686 is getting to big, it might be a better approach to slice out independent changes which can be easily reviewed and tested.

jonasschnelli added a commit to jonasschnelli/bitcoin that referenced this pull request Feb 4, 2015
According to bitcoin#3440 it would make sense to decouple the wallet and the miner (and maybe other things) from the init-/shutdown-process, etc.

This is related to bitcoin#5686, bitcoin#5744, bitcoin#5745
@jtimon
Copy link
Contributor

jtimon commented Feb 13, 2015

ut ACK

void CRPCTable::AddOrReplaceCommand(const CRPCCommand command)
{
// search after existing key in hashmap and remove it
map<string, const CRPCCommand*>::iterator it = mapCommands.find(command.name);
Copy link
Member

Choose a reason for hiding this comment

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

Why is this lookup needed? You can just overwrite using the line you have below?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm... yes. Should be sufficient to just overwrite. Will change this.

@dexX7
Copy link
Contributor

dexX7 commented Mar 4, 2015

Hey @jonasschnelli,

this is a very interesting idea. I faced some issues (segfaults and std::bad_alloc exceptions), probably related to object lifetime, and ended up passing const CRPCCommand* command, where the pointer is maintaned externally, which seemed more intuitive.

From a practical perspective, value conversion is also a relevant topic, and editing vRPCConvertParams in rpcclient.cpp fails the goal of modularity, so I created json_conversion.h, to skip conversion tables and it can be used directly on Value objects with Cast<bool>(param[0]), Cast<int16_t>(param[1]), ...

@jonasschnelli
Copy link
Contributor Author

@dexX7 Indeed. The vRPCConvertParams needs also modularization. I'll check your implementation approach and will try to update this PR.

@jonasschnelli
Copy link
Contributor Author

@dexX7 i played around with your json_conversion.h implementation and it seems to be useful. How would you solution to the call RPCTypeCheck look like? I assume when skipping the vRPCConvertParams conversion the type check no longer works?

We could get rid of the conversion via vRPCConvertParams but this would generate some changes (problem of testing/reviewing). Maybe the json_conversion.h should only be used for new calls.

@dexX7
Copy link
Contributor

dexX7 commented Mar 7, 2015

Good point, I didn't really intend to replace the old system, but it was more like a quick workaround-ish solution, although I have to admit, I don't like having a conversion table and still be required specify data types (e.g. get_str(), get_int(), ...).

I pushed three more conservative and similar, but slightly different each, approaches:

As you may see, I'm a bit lost and undecided, design wise, but I hope it helps to push this further. :)

@jonasschnelli
Copy link
Contributor Author

pulled in @dexX7 conversion table work. Fixed code nits mentioned by @sipa .

A flexible RPC interface is required if we like to add capability to switch on/off certain modules.
It's also totally required to factor out/decouple the wallet from the rest of the code.
It could be a intermediate stop in case of a new RPC implementation. But for now i think this is a feasible way.
Reviewing this means helping bitcoind to get a new wallet-implenentation while a legacy wallet could still be enabled.

jonasschnelli and others added 3 commits March 13, 2015 17:45
- this will allow a upcomming modularization of the wallet or other components
- add method to insert custom conversion entries

Conflicts:
	src/test/rpc_tests.cpp
@dexX7
Copy link
Contributor

dexX7 commented Mar 13, 2015

Adding new commands is still an issue for me, if the scope is left. For example: https://gist.github.com/dexX7/32accc4b04cb2e7dd496

@jonasschnelli
Copy link
Contributor Author

@dexX7 Thanks for the response. Yes. Bad memory management. Will have a look at it.

@jonasschnelli
Copy link
Contributor Author

@dexX7 i reviewed you gist https://gist.github.com/dexX7/32accc4b04cb2e7dd496. I would say the PR is acting correct.
When adding a rpc command over the new call AddOrReplaceCommand() you have to make sure that your CRPCCommand struct stays in memory. In your gist you create your CRPCCommand within your function void addTestCommand() but then test it in another block. const CRPCCommand newCmd get freed after exiting void addTestCommand().

I think one need to take the same approach to add commands to the vRPCCommands[] table as we do it for the standard rpc calls: static const CRPCCommand vRPCCommands[] = ....

This is not perfect but would give a RPC flexibility with a diff-size of +82/−2.

* add or replace a CRPCCommand to the dispatch table
* @param command rpc command to add or replace
*/
void AddOrReplaceCommand(const CRPCCommand command);
Copy link
Contributor

Choose a reason for hiding this comment

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

The devil is in the details here, I think. :) const CRPCCommand command creates copy of the original command, and the caller can maintain the original for the whole execution lifetime, but it would still break (try: the updated gist).

It's a slightly different story with RPCAddConversion(const std::string& method, int idx), because the lifetime the method name seems to be extended, where Temporary object lifetime, note 1 appears to apply to my understanding.

Upfront: using const CRPCCommand& command works, but the caller must still take care of the lifetime, which is not very intuitive imho, as one might be tempted to believe it's behavior is similar to the const std::string& s case, thus my comment about passing a pointer const CRPCCommand* instead, which makes it very clear that it's the caller's responsibility (in code: dexX7@57b252e).

Messing around with object lifetime and pointers is a bit cumbersome and error prone in general in my opinion, so it might be worth to overthink the whole approach of storing pointers in mapCommands, but on the other hand, keeping changes minimal and doing it step by step probably yields results more quickly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You are totally right. It must be const CRPCCommand& command (passing pointers). I just pulled in your commit.
I'm also aware that this pointer-passing-approche is not intuitive. But i'm still trying to keep the changeset-size at minimum. I also think a rpc calls will be added when the app starts (modules get loaded) then they stay alive until the app detects a shutdown so the lifetime management tend to be not so complex.

Using pointers signals the responsibility of managing object lifetime is in the hand of the caller.
jonasschnelli added a commit to jonasschnelli/bitcoin that referenced this pull request Mar 21, 2015
jonasschnelli added a commit to jonasschnelli/bitcoin that referenced this pull request Mar 21, 2015
@sipa
Copy link
Member

sipa commented Jun 16, 2015

Needs rebase.

@jonasschnelli
Copy link
Contributor Author

@sipa: i think this solution is more flexible (and also less risky): #6006. Closing this.

jonasschnelli added a commit to jonasschnelli/bitcoin that referenced this pull request Jun 24, 2015
@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.

5 participants