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

feat: examples/golang/waku.go add new example #2559

Merged
merged 5 commits into from
Mar 28, 2024
Merged

Conversation

Ivansete-status
Copy link
Collaborator

Description

This PR adds a simple example and approach on how to perform cbindings over Golang. In other words, this PR allows the integration of libwaku.so in a tiny example to demonstrate how to use it.

As a pre-requisite, the libwaku.so must exist. To compile it, make libwaku -j11.

Changes

  • Add simple Golang example that integrates libwaku.so. This example just starts a node and makes it to connect to an already running local node.

@Ivansete-status Ivansete-status changed the title feat(cbindings) examples/golang/waku.go add new example feat: examples/golang/waku.go add new example Mar 26, 2024
@Ivansete-status Ivansete-status marked this pull request as ready for review March 26, 2024 17:21
@Ivansete-status Ivansete-status self-assigned this Mar 26, 2024
Copy link
Contributor

@chaitanyaprem chaitanyaprem left a comment

Choose a reason for hiding this comment

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

LGTM

Have few queries, nothing blocker.

examples/golang/waku.go Outdated Show resolved Hide resolved

ctx := WakuNew(config)
WakuSetEventCallback(ctx)
WakuRelaySubscribe(ctx, WakuDefaultPubsubTopic(ctx))
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe best to use sharding (static/auto based on if RLN is available) as an example rather than defaultpubsubTopic?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Maybe best to use sharding (static/auto based on if RLN is available) as an example rather than defaultpubsubTopic?

ah yes, good point! I think for now we can keep this example simpler but is something to consider if we create a Golang "bindings" repo and extend the libwaku functions.

Copy link
Contributor

@SionoiS SionoiS left a comment

Choose a reason for hiding this comment

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

Never read Go before but looks good.

@@ -0,0 +1,326 @@
package main

/*
Copy link
Contributor

Choose a reason for hiding this comment

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

That's only to show the C logic we assume exist right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That's only to show the C logic we assume exist right?

I'm not an expert at all but in this case, we are using cgo, which conforms a tandem between C and Go.
These comments are handled by the Go compiler and they are part of the C-side.

Comment on lines 236 to 247
func WakuPubsubTopic(ctx unsafe.Pointer, topicName string) string {
var cTopicName = C.CString(topicName)
var str = C.allocMyString()

defer C.free(unsafe.Pointer(cTopicName))
defer C.freeMyString(str)

C.cGoWakuPubsubTopic(ctx, cTopicName, str)

var pubsubTopic = C.GoStringN(C.getMyCharPtr(str), C.int(C.getMyCharLen(str)))
return pubsubTopic
}
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 this do? Topic string into the shard format?

Copy link
Collaborator Author

@Ivansete-status Ivansete-status Mar 27, 2024

Choose a reason for hiding this comment

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

What does this do? Topic string into the shard format?

Yes, this function is aimed to simplify the creation of a well-formatted pubsubtopic.

Copy link
Member

@richard-ramos richard-ramos left a comment

Choose a reason for hiding this comment

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

Looks nice!
On the waku-go-bindings repository we can try to add more goodies to the API that we can copy from go-waku and would probably make things easier for the dev, as well as making some functions friendlier. Here are some things that come to mind. They can be done either in the new repo or here.

  1. Instead of panicing with an exit(1) in WAKU_CALL, we should return a go error in the Go API for all functions that might fail.

  2. Instead of returning an unsafe.Pointer in WakuNew, we can define the following:

type WakuContext {
     ptr unsafe.Pointer
}

func WakuNew(jsonConfig string) (*WakuContext, error) {
	// TODO: error handling in case waku_new fails, instead of exit
       ptr := C.cGoWakuNew(C.CString(jsonConfig))
       return &WakuContext{ ptr: ptr }, nil
}

for all means and purposes, it's basically the same code, but looks less scary to devs than returning an unsafe.Pointer

  1. It seems that setting an event callback requires the dev to also define a void cGoWakuSetEventCallback(void* ctx, void* myStr) on the C side? If that's the case, it will probably be necessary to add comments indicating the need to do so.

  2. In WakuContentTopic it probably makes sense to have the content topic be its own alias instead of string i.e.: type WakuContentTopic = string, same for the pubsub topic

  3. There's something strange going on with the indentation. I guess it's an IDE issue? If using vscode, consider installing the go extension, which will automatically format your code.

  4. It might make sense to instead of having separate functions, to have a single struct with methods, i.e., following the previous recommendation, you could have something like this:

package waku

type WakuNode {
     ptr unsafe.Pointer
}

func(w *WakuNode) Start() error {  ....  }
func(w *WakuNode) Stop() error {  ....  }

func New(....) (*WakuNode, error) {  }
...

That way, if you want to create a node in some project, you would do something like this:

import waku "github.com/waku-org/waku-go-bindings"
...
wakuNode, err := waku.New(theConfig)
if err != nil {
    // TODO: Handle error
}

wakuNode.Start()

...

wakuNode.Stop()
  1. In WakuNew function, instead of accepting a json, we should accept a struct, and do a json.Marshal to convert the struct to a string. That way we leave less oportunities for the devs to make mistakes building the config. This can be copied from https://github.com/waku-org/go-waku/blob/master/library/config.go#L12

  2. WakuRelayPublish should return the message hash according to the RFC

  3. It probably make sense for WakuListenAddresses to return a slice of multiaddresses (using https://github.com/multiformats/go-multiaddr) instead of returning the JSON response

// Notice that the Waku node runs in a separate thread.
time.Sleep(time.Second)
}
}
Copy link
Member

Choose a reason for hiding this comment

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

Even if the node will stop anyway once the program exits, it is probably a good idea to manually stop the node, so devs see that the function exists!

Suggested change
}
WakuStop()
}

@Ivansete-status
Copy link
Collaborator Author

@richard-ramos - I've applied all your comments but the 9.
I'll merge it for now but I'm happy to address any further suggestions in upcoming PRs :)

Thanks so much for the comments guys!

@Ivansete-status Ivansete-status merged commit 8d66a54 into master Mar 28, 2024
8 checks passed
@Ivansete-status Ivansete-status deleted the cbindings-golang branch March 28, 2024 10:19
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