-
Notifications
You must be signed in to change notification settings - Fork 374
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
emit & event built-in functions #575
Comments
Let's explore implementing this feature. Some initial questions and suggestions:
Please share your thoughts. |
I have a new idea: what if we use the following code snippet instead? import "log"
func Transfer(amount grc20.Token) {
// ...
log.Print("foobar")
} This would append a transaction receipt similar to the following: {"caller":"gno.land/r/demo/foo20","msg":"foobar"} What do you think? |
|
this looks very straightforward + easy to understand + very simple. But to be sure is that |
Yes, my suggestion is to port and adapt the official This will allow us to have transaction receipts when on-chain, while also retaining the standard |
The name of |
I personally think that the name "log" should not be used for communicating and using events; in Go it is used to add a "human interface" and what is logged should not be parsed or read by other machines - aside from what @ltzmaxwell pointed out as well. I'm more in favour of something in Here's a way I could imagine this being used: package foo // import "gno.land/r/demo/foo"
import "gno.land/r/demo/broker"
type X struct {
A int
}
const (
// EventFoo is emitted when ...
// Type: [X]
EventFoo = "foo"
)
func Emit() {
// As a guideline (and possibly future linter), a package should always emit the same
// type, and it should be documented like in this case.
broker.Emit(EventFoo, X{1})
} package bar // import "gno.land/r/demo/bar"
import (
"gno.land/r/demo/foo"
"gno.land/r/demo/broker"
)
func init() {
// There could be runtime errors (ie. Handler's argument type is not that emitted by pkg foo)
// so this is an idea of how to handle them.
broker.OnError(errorHandler)
// The listeners are scoped to the calling realm.
// Other APIs could be SetListener(pkg, evt string, fn interface{}), RemoveListeners(pkg, evt string)
broker.AddListener("gno.land/r/demo/foo", foo.EventFoo, Handler)
}
func Handler(x foo.X) {
_ = x.A
} |
Since If we want this has to be BTW @thehowl, making it realm is very interesting stuff, but I'm worried about situation where we have to upgrade pub/sub contracts. What do you think?? |
@r3v4s Are you referring to updating the |
updating Lets say...
I had similar experience in EVM, so this is my concern. Speaking of which, maybe we can make proxy contract for |
@r3v4s I spent a few words explaining how I think we should handle contract upgrades while retaining state information in this comment - so it should allow us to change |
import "std"
e := std.NewEvent("admin_added") // MakeEvent? // Native go wrapper // Event Prefix: `gnovm-`
e.AddAttributes("addr",newAdminAddr) // key string, value string IMHO, I'm not sure, but what if we treated the event that occurs in the contract as one of |
I see two things. std.Emit(std.Event)
log.Log(fmt, args...)
Rather than Tendermint1's pubsub which is made to be asynchronous (unnecessarily I would add), I would go with tm2's synchronous simple EventSwitch, which with little modification should be portable go gno. So this gno EventSwitch should be used for gno in-logic events, neither std.Emit nor log.Log. The user, if needed, can easily write a function that calls both std.Emit (or log.Log) AND EventSwitch.FireEvent. "log" to me is something cheap, and something that doesn't have any side effects. While std.Emit(std.Event) could potentially have side effects, as in, become an input to subsequent logic (in the current or a later transaction), I think there's value to having a merkle-root included event that is guaranteed to be cheap and (direct) side-effect free, where the intent is to produce a byte sequence that can be parsed from clients like wallets. If you want to emit an event that is to be read by later logic, where the event includes a (potentially) mutable object, then tm2.EventSwitch can handle that better, or some custom pubsub system that uses the persistence of realms, as @thehowl mentioned. In other words, some function probably should exist that does nothing but produce amino bytes that get included in the merkle root, and nothing else; and std.Emit should be that. Must log.Log generate abci.Events even when the tx fails? That would be very useful, but there's as of yet no way to do this. It wouldn't be hard to implement -- just need to define via PackageNode.DefineNative, to stash the logs somewhere. This function should be defined in gnoland (not gnovm), since it is a particular quirk of the usage of gno, and the gno VM doesn't need to be aware of it. BTW tm2/pkgs/sdk/vm should be moved into gno.land/pkgs/sdk/vm, then afterwards this log.Log maybe can be injected by modifying what is currently tm2/pkgs/sdk/vm/builts.go. // @piux2 @moul I suggest we move it to gno.land/pkgs/sdk/vm sooner than later. |
I'm going (would like) to start a PR about std.EmitEvent() using abci.Event :-) I probably won't be able to include it in this PR, but I think gas costs for using event should be added later. |
The initial implementation could be:
|
# Description Succeed in my predecessor's legacy. I have implemented the output to show the path where the event occurred, as discussed in #1833. Also made it print the timestamp or block height together. ## Key Changes In this change, event emission functionality has been added to the Gno. The main changes include: 1. Introducing of the `emitEvent` function: - The `emitEvent` function emits an event based on the given type and attributes - Attributes are passed as an even-length of array key-value pairs - When emitting an event, the current _package path_, _timestamp_, and _block height_ information are recorded along with the event(discussed in #1833). This metadata provides additional context about where the event occured. 2. Additional of event-related types and functions in the `sdk` packages: - `NewEvent` creates a new `Event` object based on the provided information. - `ArributedEvent` struct contains informations such as event type, package path, block height, timestamp and attributes. But I'm not sure how to utilize the `eventType` yet. So, I've just put it as a placeholder which will be a disscussion for another time. - `EventArribute` represents an attribute of an event and consists of a key-value pair - `NewEventArribute` creates a new `EventAttribute` object based on the given key-value pair. ## Example ```go package ee import ( "std" ) const ( EventSender = "sender" EventReceiver = "receiver" ) func Sender(){ SubSender() SubReceiver() } func SubSender() { std.Emit( EventSender, "key1", "value1", "key2", "value2", "key3", "value3", ) } func SubReceiver() { std.Emit( EventReceiver, "bar", "baz", ) } func Receiver() { std.Emit( EventReceiver, "foo", "bar", ) } ``` ### Result ```json [ "{\"type\":\"sender\",\"pkg_path\":\"gno.land/r/demo/ee\",\"identifier\":\"SubSender\",\"timestamp\":1713846501,\"attributes\":[{\"key\":\"key1\",\"value\":\"value1\"},{\"key\":\"key2\",\"value\":\"value2\"},{\"key\":\"key3\",\"value\":\"value3\"}]}", "{\"type\":\"receiver\",\"pkg_path\":\"gno.land/r/demo/ee\",\"identifier\":\"SubReceiver\",\"timestamp\":1713846501,\"attributes\":[{\"key\":\"bar\",\"value\":\"baz\"}]}" ] ``` ## Related Issue/PR #575 emit & event built-in functions (@r3v4s) #853 feat: event & emit in gno (@anarcher) <- previous work. #975 [META] Gno Wishlist / Feature Request Dump (@zivkovicmilos) --------- Co-authored-by: n3wbie <r3v4@onbloc.xyz> Co-authored-by: Manfred Touron <94029+moul@users.noreply.github.com>
) # Description Succeed in my predecessor's legacy. I have implemented the output to show the path where the event occurred, as discussed in gnolang#1833. Also made it print the timestamp or block height together. ## Key Changes In this change, event emission functionality has been added to the Gno. The main changes include: 1. Introducing of the `emitEvent` function: - The `emitEvent` function emits an event based on the given type and attributes - Attributes are passed as an even-length of array key-value pairs - When emitting an event, the current _package path_, _timestamp_, and _block height_ information are recorded along with the event(discussed in gnolang#1833). This metadata provides additional context about where the event occured. 2. Additional of event-related types and functions in the `sdk` packages: - `NewEvent` creates a new `Event` object based on the provided information. - `ArributedEvent` struct contains informations such as event type, package path, block height, timestamp and attributes. But I'm not sure how to utilize the `eventType` yet. So, I've just put it as a placeholder which will be a disscussion for another time. - `EventArribute` represents an attribute of an event and consists of a key-value pair - `NewEventArribute` creates a new `EventAttribute` object based on the given key-value pair. ## Example ```go package ee import ( "std" ) const ( EventSender = "sender" EventReceiver = "receiver" ) func Sender(){ SubSender() SubReceiver() } func SubSender() { std.Emit( EventSender, "key1", "value1", "key2", "value2", "key3", "value3", ) } func SubReceiver() { std.Emit( EventReceiver, "bar", "baz", ) } func Receiver() { std.Emit( EventReceiver, "foo", "bar", ) } ``` ### Result ```json [ "{\"type\":\"sender\",\"pkg_path\":\"gno.land/r/demo/ee\",\"identifier\":\"SubSender\",\"timestamp\":1713846501,\"attributes\":[{\"key\":\"key1\",\"value\":\"value1\"},{\"key\":\"key2\",\"value\":\"value2\"},{\"key\":\"key3\",\"value\":\"value3\"}]}", "{\"type\":\"receiver\",\"pkg_path\":\"gno.land/r/demo/ee\",\"identifier\":\"SubReceiver\",\"timestamp\":1713846501,\"attributes\":[{\"key\":\"bar\",\"value\":\"baz\"}]}" ] ``` ## Related Issue/PR gnolang#575 emit & event built-in functions (@r3v4s) gnolang#853 feat: event & emit in gno (@anarcher) <- previous work. gnolang#975 [META] Gno Wishlist / Feature Request Dump (@zivkovicmilos) --------- Co-authored-by: n3wbie <r3v4@onbloc.xyz> Co-authored-by: Manfred Touron <94029+moul@users.noreply.github.com>
Closed as part of #1653 🎉 |
This PR showcases a model that combines multiple contracts with defined goals and constraints. The aim is to make everything in `sys/*` usable by the chain (tm2 powered) efficiently, with minimal need for updates while maintaining flexibility in usage. The `sys/` contracts focus on defining data types and helpers to ensure that received callbacks meet minimal constraints, like GovDAO approval. They do not handle DAO logic or state due to complexity and upgradability requirements for DAOs. I won't include complete DAO examples in this PR. Imagine having these sections once everything is done: - `{p,r}/sys: minimal interface with the chain` - `{p,r}/gov: simple DAO frameworks` - `{p,r}/*`: where users will develop permissionless logic and propose it to `gov` for approval using `sys` to trigger the chain. Personal note -> try to introduce and document the notion of "pausable threads". Related with #1974. --- TODO: - [x] pseudo-code for proof of conribution's valset management. - [x] proposal example. - [ ] pseudo-code for gnosdk v0 to catch the event and apply the change from tm2. cc @gfanton - [ ] add unit-tests, to illustrate the expected usage. depends on std.Emit (#575). depends on #1948 (need rebase). --------- Signed-off-by: moul <94029+moul@users.noreply.github.com> Signed-off-by: gfanton <8671905+gfanton@users.noreply.github.com> Co-authored-by: Milos Zivkovic <milos.zivkovic@tendermint.com> Co-authored-by: gfanton <8671905+gfanton@users.noreply.github.com>
I opened this issue to discuss about emit (i.e event subscribe).
In Solidity, you can generate logs using emit & event methods
web3.eth.subscribe()
eth_newFilter()
&ð_getFilterChanges()
Theses concepts are used to communicate between Ethereum and the outside world.
Questions
Would there be any similar ways to get Gno's event from the outside world?
ws
is open by default, however a list of methods I've used on Cosmos doesn't work.Suggestions
Pub-sub
ws
. If it usesws
with extra method for subscribe, I think we can bring this concept to emit.The text was updated successfully, but these errors were encountered: