Skip to content
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

Noel/libp2p entrypoint #398

Merged
merged 59 commits into from
Nov 16, 2021
Merged

Noel/libp2p entrypoint #398

merged 59 commits into from
Nov 16, 2021

Conversation

kwannoel
Copy link
Contributor

@kwannoel kwannoel commented Sep 24, 2021

Implement Barebones of: #106.

Run buy_sig over libp2p

To run the buy_sig interaction over libp2p, in one terminal run:

a_addr=/ip/127.0.0.1/tcp/10333
./glow start-interaction -O $a_addr -E pet -C libp2p -W

You will be prompted:

Starting libp2p client
I am /ip4/127.0.0.1/tcp/10333/ipfs/<PeerId>
...

Copy that into dest in the second terminal, and run:

b_addr=/ip/127.0.0.1/tcp/10300
dest=/ip4/127.0.0.1/tcp/10333/ipfs/<PeerId>
./glow start-interaction -O $b_addr -C libp2p -E pet -D $dest --database alice

Select the relevant options to run the buy_sig interaction.

Run the buy_sig over libp2p test case locally

./unit-tests.ss test t/buy-sig-libp2p-local-integration-test.ss

Progress

  • Use user-supplied keypair to derive peerid.

    • Supply user keypair to daemon via gerbil-libp2p.
      • Figure out where to pass this option to go-libp2p-daemon via gerbil-libp2p.
        See: Noel/libp2p entrypoint #398 (comment)
      • Extract privatekey using methods from gerbil-ethereum/known-addresses.ss.
      • Convert privatekey into protobuf format.
      • Store protobuf into file.
      • Pass filename to libp2p daemon using options: ["-id" filename].
  • Backend support and CLI to ensure the go-libp2p-daemon and/or JS library is started with the correct parameters (toggling libp2p, keypairs).

    • Update CLI start-interaction entrypoint to take in an option, which toggles off-chain communication between stdout and libp2p.
    • Q: Should the off-chain channel be part of the agreement?
      A: No, it is determined before the agreement itself,
      Since it specifies the channel through which the agreement is sent.
    • Store this into runtime object.
    • Add a wait-for-agreement flag, which waits for other party to supply interaction agreement.
    • Initialize libp2p-client
  • Backend support and CLI to send and receive handshakes and agreements.

    • Parameterize outgoing message handlers over channel.
    • Parameterize incoming message handlers over channel.
    • Stub handlers for outgoing messages over libp2p
    • Stub handlers for incoming messages over libp2p
    • Listen for handshake / agreements
      • Persist listening thread
      • store things in a buffer
        • store, push for buffer.
      • store this message buffer in channel object
    • Implement outgoing message over libp2p
    • Implement incoming message over libp2p

Polishes

Priority

  • Purge keypair file once client has been initialized.
    - [] Randomly generate keypair file.
  • Review and cleanup code (FIXMEs, TODOs, repeated parts).
  • If alice starts first, poll until bob comes online.
  • Cleanup output
  • Documentation
  • Write integration test (buy_sig).

@kwannoel kwannoel mentioned this pull request Sep 24, 2021
22 tasks
@kwannoel kwannoel force-pushed the noel/libp2p-entrypoint branch from 9fa07fb to ecadde4 Compare October 1, 2021 19:13
@kwannoel
Copy link
Contributor Author

kwannoel commented Oct 6, 2021

How to initialize libp2p daemon with participant keypairs

See https://github.com/libp2p/go-libp2p-daemon for installing p2pd, p2p-keygen.
Use the -id flag to configure private-key when starting daemon:

p2pd -id <private_key_file>

Use the following command to generate sample private keys:

p2p-keygen -f <private_key_file

@kwannoel kwannoel force-pushed the noel/libp2p-entrypoint branch from 2fff30f to 458f78f Compare October 7, 2021 17:31
cli/interaction.ss Outdated Show resolved Hide resolved
@kwannoel kwannoel force-pushed the noel/libp2p-entrypoint branch from 4f694c3 to e700e92 Compare October 25, 2021 07:01
cli/interaction.ss Outdated Show resolved Hide resolved
@kwannoel kwannoel marked this pull request as ready for review November 1, 2021 18:49
@kwannoel kwannoel force-pushed the noel/libp2p-entrypoint branch from 2f9ebe0 to b9cda36 Compare November 1, 2021 20:10
Copy link
Contributor

@zenhack zenhack left a comment

Choose a reason for hiding this comment

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

Some comments in-line. Seems reasonable at a high level.

(dest-address dest-address)
(my-nickname my-nickname)
(contacts contacts)))
(def off-chain-channel (init-off-chain-channel channel-options)) ; FIXME: Teardown
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 the fixme could stand to be spelled out a bit more; what exactly needs to happen? (It looks like there's something related in the finally block).

Copy link
Contributor Author

@kwannoel kwannoel Nov 8, 2021

Choose a reason for hiding this comment

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

Was already fixed in the finally block, forgot to remove the FIXME.
Have removed it.

(def (make-libp2p-socket-path address: address host-address: host-address)
(def multiaddr-hash
(let (address-str (.call Address .string<- address))
(u8vector->base64-string (sha256 (string-append address-str host-address)))))
Copy link
Contributor

Choose a reason for hiding this comment

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

Should probably add urlsafe?: #t here; default base64 can include slashes.

Copy link
Contributor Author

@kwannoel kwannoel Nov 11, 2021

Choose a reason for hiding this comment

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

Removed this function (make-libp2p-socket-path), it has become obsolete.
For future reference, if I were to use u8vector->base64-string, the urlsafe option can be found here: https://cons.io/reference/text.html#subu8vector-base64-string

(u8vector->base64-string (sha256 (string-append address-str host-address)))))
(string-append "/tmp/libp2p-socket-" multiaddr-hash))

(def (with-seckey-tempfile nickname: nickname c)
Copy link
Contributor

Choose a reason for hiding this comment

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

The variable name c seems like an odd choice here; maybe something more descriptive?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated.

('libp2p (let ()
(def my-nickname (hash-get options 'my-nickname))
(def host-address (hash-get options 'host-address))
(def dest-address (hash-get options 'dest-address))
Copy link
Contributor

Choose a reason for hiding this comment

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

In general, use hash-ref instead of hash-get unless you actually want it to return #f if the key is not present (hash-ref throws an exception). This has been the source of more than one bug in the past.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated. Thanks!

runtime/participant-runtime.ss Show resolved Hide resolved
(force-output))

;; TODO: Generalize & Upstream to gerbil-utils/json
(def (escape-json-string json-string)
Copy link
Contributor

Choose a reason for hiding this comment

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

There are a couple things wrong here:

  • Conceptually, this is really supposed to be doing shell escaping; it has nothing to do with json per se.
  • More importantly, it does not correctly escape things for the shell. E.g:
    • "$(rm -rf /) ''" would be passed through unchanged, since it contains a single quote.
    • If you got rid of that first case, then "'$(rm -rf /)'" would still slip by the escaping in the second case; due to the way shell escaping works, you can unquote back into an interpreted context. So you also need to substitute out any single quotes in the middle of the string.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Renamed this function to be more specific, and added your remarks inline as a TODO, before this can generalized as a way to shell-escape json strings.

(loop))))))


;; ------------------ Libp2p client methods
Copy link
Contributor

Choose a reason for hiding this comment

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

This could do with a link to some relevant documentation; this all seems very magical, not knowing a-priori much about the protocol.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added more documentation, thanks for pointing this out.

;; (write-u8 #x1b)
;; (displayln "[0m")
;; (display "> ")
;; (displayln "*** Done")
Copy link
Contributor

Choose a reason for hiding this comment

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

Should probably just get rid of commented out code like this (and similarly in chat-handler 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.

Removed

;; Wait for handshake to come in
(thread-sleep! 10)
;; (displayln "2")
;; (force-output)
Copy link
Contributor

Choose a reason for hiding this comment

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

Should not leave code commented out like this.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed

@@ -0,0 +1,219 @@
(export #t)
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm kindof wary of continuing to copy & paste the bulk of the logic for these integration tests; it might be prudent to try to factor some of this out into a function.

Copy link
Contributor Author

@kwannoel kwannoel Nov 15, 2021

Choose a reason for hiding this comment

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

Refactored the boilerplate for setting up the test environment into a function. The other areas seem to be specific to the integration test itself (options we pass in etc...)

@kwannoel kwannoel force-pushed the noel/libp2p-entrypoint branch from e517484 to 75702ef Compare November 11, 2021 20:29
@kwannoel kwannoel force-pushed the noel/libp2p-entrypoint branch from d0ff975 to c00abcc Compare November 15, 2021 11:28
(if host-addrs ["-hostAddrs" host-addrs] [])...
options ...]))
(cmd (format "{ echo ~a ; exec ~a ; } < /dev/null >> ~a 2>&1"
raw-cmd raw-cmd p2pd-log-path))
Copy link
Contributor

Choose a reason for hiding this comment

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

A more direct way to print the executed commands would be to just pass -x to the shell.

Copy link
Contributor

@zenhack zenhack left a comment

Choose a reason for hiding this comment

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

A couple more minor things, but this mostly looks reasonable to me.

;; TODO: Once the above changes are upstreamed for `start-libp2p-daemon!',
;; this command can be made obsolete too.
(def (open-libp2p-client host-addresses: (host-addresses #f) options: (args []) address: (sock #f) wait: (timeo 12) (path #f)) ;; Extra arguments host-address and options
(let (d (start-libp2p-daemon! host-addresses: host-addresses options: args address: sock wait: timeo)) ;; Should go with host-address/tranpsort/port
Copy link
Contributor

Choose a reason for hiding this comment

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

These lines are very long and it makes it hard to read; maybe wrap them, with one key/value per line?

;; See: https://docs.libp2p.io/concepts/protocols/#handler-functions
(def chat-proto "/chat/1.0.0")

;; This function reads the
Copy link
Contributor

Choose a reason for hiding this comment

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

You seem to have lost part of this sentence.

help: "command to use to transfer handshakes")
;; TODO: Abstract into Enum - See gerbil-poo
;; enum off-chain-channel = 'stdio | 'libp2p
(option 'off-chain-channel-selection "-C" "--off-chain-channel" default: 'stdio
Copy link
Contributor

Choose a reason for hiding this comment

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

What does the conversion from string to symbol?

;; FIXME: Mark off-chain-channel as experimental, print it in a console prompt
(def channel-options
(hash
(off-chain-channel-selection (symbolify off-chain-channel-selection))
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe validate that?

fare added a commit that referenced this pull request Nov 16, 2021
@fare fare merged commit 85e20aa into master Nov 16, 2021
@bennewhall
Copy link
Contributor

I was having issues running this initially, however it worked when I did
a_addr=/ip4/127.0.0.1/tcp/10333
and
b_addr=/ip4/127.0.0.1/tcp/10300

I think something having to do with /ip not being a protocol

@fare fare deleted the noel/libp2p-entrypoint branch January 8, 2022 04:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants