-
Notifications
You must be signed in to change notification settings - Fork 38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add guide on how to connect local nodes #107
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you so much for this guide! I think it's a great demonstration, it's super simple and I learned a lot in just these few lines of code. I was thinking (see my specific comments) that maybe instead of assert
ing specific outputs from the peer list -- could we actually show how the SPV / Fullnode relationship works? Like, add an address to the SPV bloom filter and then demonstrate how the Fullnode alerts the SPV. Perhaps the easiest way would be to hard-code an address for the SPV node to watch:
spvNode.pool.watchAddress('RCFhpyWXkz5GxskL96q4KtceRXuAMnWUQo')
...and then generate a block to that address from Fullnode:
fullNode.rpc.generateToAddress([1, 'RCFhpyWXkz5GxskL96q4KtceRXuAMnWUQo')
You could also generate a block to a different address just to indicate that Fullnode would not relay that to SPV node.
Again, great work and thanks! Let me know what you think of these changes. I'm excited to add this to bcoin.io!
|
||
// no peers for the spvNode yet :( | ||
console.log('spvNode\'s peers before connection:', spvNode.pool.peers.head()); | ||
assert.equal(spvNode.pool.peers.head(), null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I ran this script, I actually already had a peer:
spvNode's peers before connection: <Peer: handshake=false host=18.191.95.172:48445 outbound=true ping=-1>
...and so the assert failed. (That's the IP address of my own server). The "before connection" printout is interesting, but I don't know if we need the assert
there... unless there is some other way to definitively clear all peers before starting.
spvNode.pool.peers.add(peer); | ||
|
||
// allow some time to establish connection | ||
await delay(3000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually had to change this delay to 10 seconds delay(10000)
on my machine or the second assert would fail. I wonder if we could use an await/async method here instead of gambling on how long the connection will take? I haven't tested this yet but maybe peer.open()
? https://github.com/bcoin-org/bcoin/blob/master/lib/net/peer.js#L347-L361
// nodes are now connected! | ||
console.log('spvNode\'s peers after connection:', spvNode.pool.peers.head()); | ||
assert.equal(spvNode.pool.peers.head().inspect(), | ||
'<Peer: handshake=true host=127.0.0.1:48445 outbound=true ping=-1>'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once I adjusted the timeout above and commented out the first assert, this assert succeeded. But still, again, I think it is a long string to assert equality. See my main review comment for my idea on how to wrap this up nicely.
Thanks for the constructive suggestions. These would make the example much more robust and informative. Avoiding timeouts and |
Another question. It seems that the example you gave with the |
Hi @OrfeasLitos ! Sorry took me a few days to play with this and get back. Here's where I ended up with the script: https://gist.github.com/pinheadmz/66f1ff9ae44ef594f0857987b075da77 You can take or leave whatever you want from there, see what you think. But here's kinda the gist of that... gist:
I look forward to your update! Thanks again and let me know if you have any other questions or run into any other weirdness :-) |
I like your approach, with the logging and I used the tool In slightly older commits, the SPV node used to correctly receive only one transaction! The regression happens here: bcoin-org/bcoin@a0ac953 . If it is fixed, we can simply send the two txs and avoid the blocks. This solution seems better because the difference between the two blocks as printed is too small. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dude thanks again so much for this contribution! I think it's almost ready to go, checking on the bug fix right now... I am super-duper amazed you caught that!
OK - @tuxcanfly found the bug and is working on a fix. SO I'd say, in addition to the small comments below, let's go with your plan: remove all the block stuff and make it about the transactions instead.
Maybe just add a comment either in the code or in the text description about why one TX goes to the SPV and the other doesn't (because of the bloom filter)
logConsole: false, | ||
logLevel: 'spam', | ||
|
||
// reduce log spam on SPV node (won't warn on Full node) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sorry this is my typo, it should say won't work on full node
-- the full node will still try to connect to that 1 outbound peer and the log will fill up anyway. maxOutbound: 0
returns an error, I tried it :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, now I see what you meant. Maybe we can achieve the intended behaviour by making the full node selfish
. I'll try it and add it if it reduces logging but still broadcasts stuff (I suppose it should).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will add a comment explaining why selfish
and why users shouldn't do it in general :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought selfish
prevented all blocks and txs from going out...? My intent with the maxOutbound
was just to reduce the attempt to connect to peer
stuff in the log... it's not that crucial either way :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apparently selfish
mode doesn't work. First of all, selfish nodes do not connect to spv nodes. Second, even if I try to undo some of the damage done by the selfish
flag, apparently the handshake fails with the (selfish) full node never sending back the verack
packet... Probably what I tried to do is unsupported, but still it's weird behavior. Anyway, let's forget the selfish
trick.
gracefully closed. | ||
|
||
The script should work out of the box, the only requirement is having `bcoin` | ||
installed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had to install p-event
on my system as well :-)
Can you add a little instruction for that? Maybe a one-line description of the package as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, I forgot to change the prose as well.
I will try to see if the example works with txs on the latest |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! Just a couple small suggestions but this looks great!
Start and manually connect two regtest nodes in a single script. | ||
``` | ||
|
||
When we start two nodes in the regtest (loopback network, 127.0.0.1) with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"on the regtest network" instead of "in the regtest"
When we start two nodes in the regtest (loopback network, 127.0.0.1) with | ||
manually set ports, they don't get connected automatically because they don't | ||
know each other's port. We thus have to connect them manually. In this example | ||
we will fire up one SPV and one Full node and initiate a connection from the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think either "Full Node" or "full node". SPV is capitalized because it's an acronym, but "Full" isn't a proper noun on its own
manually set ports, they don't get connected automatically because they don't | ||
know each other's port. We thus have to connect them manually. In this example | ||
we will fire up one SPV and one Full node and initiate a connection from the | ||
SPV side. The SPV node is given the address of the Full node and attempts to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here.
know each other's port. We thus have to connect them manually. In this example | ||
we will fire up one SPV and one Full node and initiate a connection from the | ||
SPV side. The SPV node is given the address of the Full node and attempts to | ||
connect. If everything goes well, the two nodes connect. The Full node then |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here. Also, let's split the paragraph here when you start talking about transactions (easier to read smaller paragraphs and this is kind of another section). So "Next, we'll have the full node broadcast two transactions."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 I also rephrased the first sentence of the newly split paragraph to "To demonstrate that the connection was successful, we'll have full node..." to make clear why on earth we deal with txs.
by the SPV node and the second isn't. Finally the two nodes are gracefully | ||
closed. | ||
|
||
We use the library `p-event` which promisifies events in order to `await` for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool!
httpPort: 48449, // avoid clash of ports | ||
|
||
// write log file and chain data to specific directory | ||
prefix: '~/connect-test/SPV', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
small nit, but it might be nice to make ~/connect-test
a constant since it's used in multiple places. This is nice in case someone forgets to change both and ends up with two different project directories. Also if you use node's os.homedir()
method instead of ~
it can work across platforms since I don't think Windows recognizes ~
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't windows use backslashes instead of slashes as well? I don't have a windows box to test upon, but I think something in the lines of https://gist.github.com/domenic/2790533 should be used. More info: https://nodejs.org/docs/latest/api/path.html. I think I got it correctly; At least my box is happy. If anyone can test it on a windows box, please tell me if it works for them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, the beauty if using Node's os
module is that it will take care of environment specific conditions for you so you don't even have to worry about it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i.e.
const prefix = `${require('os').homedir()}/connect-test/SPV`
if you look at the bcfg library which manages this in bcoin, it makes heavy use of this convention, even explicitly replacing instances of ~
passed by the user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for pointing me there, I found path.join()
which accomplishes what I wanted more simply than path.format()
. Let me know if you'd like any more changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! Thanks for the contribution.
Demo of two regtest nodes connecting. Resolves #106.