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

Sample protos build #5582

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open

Sample protos build #5582

wants to merge 8 commits into from

Conversation

karthikiyer56
Copy link
Contributor

PR Checklist

PR Structure

  • This PR has reasonably narrow scope (if not, break it down into smaller PRs).
  • This PR avoids mixing refactoring changes with feature changes (split into two PRs
    otherwise).
  • This PR's title starts with name of package that is most changed in the PR, ex.
    services/friendbot, or all or doc if the changes are broad or impact many
    packages.

Thoroughness

  • This PR adds tests for the most critical parts of the new functionality or fixes.
  • I've updated any docs (developer docs, .md
    files, etc... affected by this change). Take a look in the docs folder for a given service,
    like this one.

Release planning

  • I've reviewed the changes in this PR and if I consider them worthwhile for being mentioned on release notes then I have updated the relevant CHANGELOG.md within the component folder structure. For example, if I changed horizon, then I updated (services/horizon/CHANGELOG.md. I add a new line item describing the change and reference to this PR. If I don't update a CHANGELOG, I acknowledge this PR's change may not be mentioned in future release notes.
  • I've decided if this PR requires a new major/minor version according to
    semver, or if it's mainly a patch change. The PR is targeted at the next
    release branch if it's not a patch change.

What

[TODO: Short statement about what is changing.]

Why

[TODO: Why this change is being made. Include any context required to understand the why.]

Known limitations

[TODO or N/A]

Copy link
Member

@leighmcculloch leighmcculloch left a comment

Choose a reason for hiding this comment

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

Couple thoughts inline.

Comment on lines 7 to 8
// String returns a human-readable representation of the Address.
func (a *Address) Strings() string {
Copy link
Member

Choose a reason for hiding this comment

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

Typo? Comment says String, function says Strings. Typically the interface to implement is "String".

Suggested change
// String returns a human-readable representation of the Address.
func (a *Address) Strings() string {
func (a *Address) String() string {

Copy link
Contributor Author

@karthikiyer56 karthikiyer56 Feb 4, 2025

Choose a reason for hiding this comment

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

this was just to show the presence of helper/receiver functions for the generated golang code
I cant have a function called String() on that data type, since protoc genertes a String() function for you, so I lazily, for demonstration purposes, called it Strings()

Comment on lines +7 to +12
message Address {
oneof address_type {
string smartContractAddress = 1; // Smart Contract address
string accountAddress = 2; // Account address
string liquidityPoolHash = 3; // Liquidity Pool hash
string claimableBalanceId = 4; // Claimable Balance ID
Copy link
Member

@leighmcculloch leighmcculloch Feb 4, 2025

Choose a reason for hiding this comment

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

Could we make these a strkey instead? Or is there a reason to go the structured type? (Thoughts @chowbao?)

Liquidity Pools and Claimable Balances are likely to get strkeys as part of the work on CAP-67 and be rendered as strkeys in the XDR-JSON, so you could use the same format here.

We can move along strkey definitions for them to unblock any work that might be dependent on them.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm is there a reasonable way to calculate the strkey for lp and claimable balances? I would say if it's added to the strkey lib then yes I would agree with using them.

One thing to note is that would be net new and would need existing systems to know to use the strkey lp instead of hash going forward (not blocking but would "break" things like stellar-etl)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am not even sure what you guys mean when you say strkey.

The reason the Address is structured as a oneof is to align with the enum SCAddressType - the one that will be extended to add Liquiditypools and CBs as a part of CAP-67

Copy link
Contributor

@chowbao chowbao Feb 4, 2025

Choose a reason for hiding this comment

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

https://github.com/stellar/go/tree/master/strkey

It's basically the way to get the G*/C* address
https://github.com/stellar/go/blob/master/strkey/main.go#L20-L44

Leigh is saying they are gonna give liquidityPools and claimableBalances these strkeys (unless I'm also incorrect 😅)

Edit: "way to get" isn't the correct term. It's just the definition of the G/C/T etc...

Copy link
Contributor Author

@karthikiyer56 karthikiyer56 Feb 4, 2025

Choose a reason for hiding this comment

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

so, basically, you are saying that the Address can just be a proto string then, for this token_transfer_event.proto`?

Copy link
Member

@leighmcculloch leighmcculloch Feb 4, 2025

Choose a reason for hiding this comment

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

Strkeys is the format of Stellar Addresses and other Stellar entities, they're defined in SEP-23:

// Address message with oneof for different address types
message Address {
oneof address_type {
string smartContractAddress = 1; // Smart Contract address
Copy link
Member

Choose a reason for hiding this comment

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

Suggestion, the longer form is unnecessary. Elsewhere in code we simply refer to them as contract addresses:

Suggested change
string smartContractAddress = 1; // Smart Contract address
string contractAddress = 1; // Contract address

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Noted.
I want to point out that I want this PR to be used to decide on structure of the code, more than what goes inside the eventual proto data model will look like
That will be worked upon in a separte PR. review comments from here will be addressed there.

Copy link
Member

Choose a reason for hiding this comment

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

It's undesirable to group all types into a functional package like "proto" rather than a domain focused package which will be the location where they'll be used.

For example, if as a dev using the ingest SDK I'm browsing the ingest package docs, and am looking for related and interesting types, I won't see any there because they're all defined outside the ingest package in the 'protos' package. When I look at the protos package I'll see an assortment of types that relate to the ingest SDK, and potentially others that don't assuming it becomes a general place to place any protos for anything in the monorepo.

Is it possible to generate the protos within each application or package where they'll be used? So that the proto types for a specific processor are grouped with that processor?

Copy link
Contributor Author

@karthikiyer56 karthikiyer56 Feb 4, 2025

Choose a reason for hiding this comment

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

I am not entirely sure I understand the concern here, but Ima try to provide my reasoning

Its not uncommon for all the proto defintions for a particular project to be nested under one directory called protos.
This is especially needed when protos need to import another protos that are defined in a separate directory structure.

Re:

When I look at the protos package I'll see an assortment of types that relate to the ingest SDK, and potentially others that don't assuming it becomes a general place to place any protos for anything in the monorepo....

The protos are not exported as a one big package per se. As a matter of fact there is no package protos at all.
The option go_package field that I specify in the .proto files already separates the resulting golang code logically, if that is what your concern was.
the proto definitions are just co-housed together, is all
The packages generated (address/asset/token_transfer), in a sense, do follow the go idomatic way

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I could very well move this entire protos inside the ingest/ directory
That way it is all under ingest, if thats what you were suggesting?

Copy link
Contributor Author

@karthikiyer56 karthikiyer56 Feb 4, 2025

Choose a reason for hiding this comment

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

oh wait, I think I mistook what you were asking @leighmcculloch
did you mean that we still have the top level protos directory have the .proto files, as is the case in this pr, , but generate the golang bindings in a place that is closer to the token_transfer_processor implementation?

Copy link
Member

Choose a reason for hiding this comment

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

The option go_package field that I specify in the .proto files already separates the resulting golang code logically, if that is what your concern was.

Yes this was my concern because I saw .pb.go files ending up in a protos/ directory. Ideally the go types live with their respective SDKs / directories.

Ideally .proto files would live there too, but I understand that's not a desirable tradeoff.

Copy link
Contributor Author

@karthikiyer56 karthikiyer56 Feb 5, 2025

Choose a reason for hiding this comment

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

@leighmcculloch - I made it so that the data model for tokenTransferEvent is generated under where the code will potentially reside.

And I am hoping that all the new code for the upcoming proccessors is under /ingest/processors

Now, assuming that the new place for these processors in under ingest/processors/<processor_name>/,
the as long as the corresponding .proto files follow the same directory structure under /protos

i.e

  1. /protos/address/address.proto --> /ingest/address/address.pb.go (Additionally, added a helper file with receiver functions in /ingest/address)
  2. /protos/asset/asset.proto --> /ingest/asset/asset.pb.go (Additionally, added a helper file with receiver functions in /ingest/asset/)
  3. The main one
    /protos/processors/token_transfer/token_transfer_event.proto --> /ingest/processors/token_transfer/token_transfer_event.pb.go

There are a few important points to note here:

  • We should actually not be using the option go_path in the .proto files themselves. I dont know why I thought it was a good idea when i used it the first time around, or even when I wrote this comment. I have since revised my stance
  • Instead, I got creative with the Makefile target, and achieved the same sentiment using -go_opts and the -M flag. Checkout the commit message, where I explain why I did that
    cc @tamirms

…d re-order code

 The real ingenuity is in the Makefile target - "generate-proto"
 Specifying the option go_package in the .proto files would be a bad idea,
 especially if and when we plan to pull the protos into their own repo

 If someone wants to generate their own go-bindings from the proto files,
 assuming the proto files are in their own repo,
 then they wont have been able to do it properly.
 They would have to contend with the fact that the option go_package
 points to "github.com/stellar/go/ingest/...." and they would not be able
 to rename the pakcage/location for the generated go code.

 So, it is best to be clever with your Makefile target to achieve the same thing,
 with the use of the -go_opt and -M flags, instead of using option go_package
@@ -1,7 +1,7 @@
syntax = "proto3";

package token_transfer;
option go_package = "github.com/stellar/go/protos/processors/token_transfer;token_transfer";
//option go_package = "github.com/stellar/go/protos/processors/token_transfer;token_transfer";
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a big no-no
I have left it commented out, instead of deleting, for the sake of clarity, in this PoC PR

echo " $(PROTO_FILES)"; \
protoc -I=$(PROTO_DIR) \
--go_out=ingest --go_opt=paths=source_relative \
--go_opt=$$MAP_OPTS \
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Use -go_opt with the M flag to indicate what the package location/path inside the generated proto should look like

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.

3 participants