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(gnovm, tm2): implement event emission with std.Emit #1653

Merged
merged 65 commits into from
Apr 30, 2024
Merged
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
c67e718
[WIP] feat(gnovm, tm2): Yet Another Emit/Event
notJoon Feb 13, 2024
d7cb7d9
add test for e&e and change file names
notJoon Feb 22, 2024
94ab8ef
Merge branch 'master' into emit-event
notJoon Mar 26, 2024
c06f079
fixup
notJoon Mar 26, 2024
5360fa9
feat: EmitEvent in gno
r3v4s Mar 28, 2024
79f5752
fmt
notJoon Mar 29, 2024
fd84dc5
Merge branch 'master' into emit-event
notJoon Apr 1, 2024
35ef5f8
Event holds more metadata
notJoon Apr 1, 2024
0afd6cd
run go generate
notJoon Apr 1, 2024
6625e7e
fix lint error
notJoon Apr 1, 2024
2a87886
Merge branch 'master' into emit-event
notJoon Apr 2, 2024
d7f1fed
pkgPath in Events
notJoon Apr 2, 2024
2a6084a
re-organize code
notJoon Apr 2, 2024
97e2c07
print attribute
notJoon Apr 2, 2024
860e9bd
print metadata finish
notJoon Apr 2, 2024
63c5829
fix CI failing
notJoon Apr 2, 2024
943ac20
Merge branch 'master' into emit-event
notJoon Apr 3, 2024
866250e
change timestamp to expose the block header data
notJoon Apr 11, 2024
2a99d96
Merge branch 'master' into emit-event
notJoon Apr 11, 2024
3e5636b
fix failing error
notJoon Apr 11, 2024
be033a7
remove height, don't panic
notJoon Apr 12, 2024
52e5412
expose function name
notJoon Apr 12, 2024
1a9a524
save
notJoon Apr 12, 2024
f054d67
event stringfy
notJoon Apr 12, 2024
2adfdd7
fix CI
notJoon Apr 12, 2024
ebb387a
json style event string
notJoon Apr 13, 2024
bb80a2e
Update gnovm/tests/file.go
notJoon Apr 17, 2024
61bc407
fix: apply suggestions
notJoon Apr 17, 2024
e76e231
fix: apply suggestions
notJoon Apr 17, 2024
87d4d9e
Merge branch 'master' into emit-event
notJoon Apr 17, 2024
929eb6d
fix: resolve simple comments
notJoon Apr 18, 2024
49f1d84
moving previous DetailedEvent type into gnovm dir and renamed it
notJoon Apr 18, 2024
9b183fb
valid json
notJoon Apr 18, 2024
d2a0c98
fix: lint, remove leftover
notJoon Apr 18, 2024
59c020f
fix: apply some comments
notJoon Apr 19, 2024
13d7b4f
use EventString
notJoon Apr 19, 2024
9f726ca
remove leftover
notJoon Apr 19, 2024
271651a
Update gnovm/stdlibs/std/emit_event.go
notJoon Apr 22, 2024
b207069
Update gnovm/stdlibs/std/emit_event.go
notJoon Apr 22, 2024
d1c28cc
Update tm2/pkg/bft/abci/types/types.go
notJoon Apr 22, 2024
849ac83
Merge branch 'master' into emit-event
notJoon Apr 22, 2024
2e9d9ed
add very basic test
notJoon Apr 22, 2024
1d83801
add more tests
notJoon Apr 23, 2024
2ab7577
Update gnovm/stdlibs/std/emit_event.go
moul Apr 23, 2024
5a16ac6
explicit regex, remove unnecessary marshaling step.
notJoon Apr 23, 2024
ffb66ae
update comment
notJoon Apr 23, 2024
e49793a
store result to EventString
notJoon Apr 23, 2024
ff0877f
Update tm2/pkg/crypto/keys/client/maketx.go
moul Apr 24, 2024
8ddfd0f
Update gno.land/cmd/gnoland/testdata/event.txtar
notJoon Apr 24, 2024
55b6704
Update gnovm/stdlibs/std/emit_event_test.go
notJoon Apr 24, 2024
a7ae1a7
Update gnovm/stdlibs/std/native.go
notJoon Apr 24, 2024
191c130
Update gnovm/stdlibs/std/emit_event.gno
notJoon Apr 24, 2024
1474c0d
Update gnovm/stdlibs/std/context.go
notJoon Apr 24, 2024
150fe46
no regex
notJoon Apr 24, 2024
ed5f542
fixup (maybe)
notJoon Apr 25, 2024
67a40e2
fixup
notJoon Apr 25, 2024
ae5292a
Merge branch 'emit-event' of https://github.com/notJoon/gno-core into…
notJoon Apr 25, 2024
6cd31f1
fix: CI failing
notJoon Apr 25, 2024
c8219e4
Apply suggestions from code review
moul Apr 26, 2024
7e391a9
change field name and remove EmittedEvents, no global consst in test
notJoon Apr 29, 2024
96f7ca5
panic
notJoon Apr 29, 2024
0358dd6
Merge branch 'master' into emit-event
notJoon Apr 29, 2024
317108a
func name change
notJoon Apr 29, 2024
b0d9b28
Merge branch 'master' into emit-event
moul Apr 29, 2024
7a5fd74
use attrs for field name and change to use loadpkg
notJoon Apr 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion gno.land/cmd/gnoland/testdata/addpkg.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ gnokey maketx call -pkgpath gno.land/r/foobar/bar -func Render -gas-fee 1000000u
stdout '("hello from foo" string)'
stdout 'OK!'
stdout 'GAS WANTED: 2000000'
stdout 'GAS USED: [0-9]+'
stdout 'GAS USED: \d+'
stdout 'EVENTS: null'

-- bar.gno --
package bar
Expand Down
60 changes: 60 additions & 0 deletions gno.land/cmd/gnoland/testdata/event.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# start a new node
gnoland start

gnokey maketx addpkg -pkgdir $WORK -pkgpath gno.land/r/demo/ee -gas-fee 1000000ugnot -gas-wanted 2500000 -broadcast -chainid=tendermint_test test1
stdout OK!
stdout 'GAS WANTED: 2500000'
stdout 'GAS USED: [0-9]+'
stdout 'EVENTS: null'
notJoon marked this conversation as resolved.
Show resolved Hide resolved

gnokey maketx call -pkgpath gno.land/r/demo/ee -func Sender -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1
stdout OK!
stdout 'GAS WANTED: 2000000'
stdout 'GAS USED: [0-9]+'
stdout 'EVENTS: \[?.*sender.*SubSender.*receiver.*SubReceiver.*\]'
notJoon marked this conversation as resolved.
Show resolved Hide resolved
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved

gnokey maketx call -pkgpath gno.land/r/demo/ee -func Receiver -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1
stdout OK!
stdout 'GAS WANTED: 2000000'
stdout 'GAS USED: [0-9]+'
stdout 'EVENTS: \[?.*(R|r)eceiver.*\]'

-- ee.gno --
package ee

import (
"std"
)

const (
EventSender = "sender"
EventReceiver = "receiver"
notJoon marked this conversation as resolved.
Show resolved Hide resolved
)

func Sender(){
SubSender()
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved
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",
)
}
5 changes: 5 additions & 0 deletions gno.land/pkg/sdk/vm/keeper.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@
OrigSendSpent: new(std.Coins),
OrigPkgAddr: pkgAddr.Bech32(),
Banker: NewSDKBanker(vm, ctx),
EventLogger: ctx.EventLogger(),
}
// Parse and run the files, construct *PV.
m2 := gno.NewMachineWithOptions(
Expand Down Expand Up @@ -263,6 +264,7 @@
OrigSendSpent: new(std.Coins),
OrigPkgAddr: pkgAddr.Bech32(),
Banker: NewSDKBanker(vm, ctx),
EventLogger: ctx.EventLogger(),
}
// Construct machine and evaluate.
m := gno.NewMachineWithOptions(
Expand Down Expand Up @@ -334,6 +336,7 @@
OrigSendSpent: new(std.Coins),
OrigPkgAddr: pkgAddr.Bech32(),
Banker: NewSDKBanker(vm, ctx),
EventLogger: ctx.EventLogger(),
}
// Parse and run the files, construct *PV.
buf := new(bytes.Buffer)
Expand Down Expand Up @@ -463,6 +466,7 @@
// OrigSendSpent: nil,
OrigPkgAddr: pkgAddr.Bech32(),
Banker: NewSDKBanker(vm, ctx), // safe as long as ctx is a fork to be discarded.
EventLogger: ctx.EventLogger(),

Check warning on line 469 in gno.land/pkg/sdk/vm/keeper.go

View check run for this annotation

Codecov / codecov/patch

gno.land/pkg/sdk/vm/keeper.go#L469

Added line #L469 was not covered by tests
}
m := gno.NewMachineWithOptions(
gno.MachineOptions{
Expand Down Expand Up @@ -523,6 +527,7 @@
// OrigSendSpent: nil,
OrigPkgAddr: pkgAddr.Bech32(),
Banker: NewSDKBanker(vm, ctx), // safe as long as ctx is a fork to be discarded.
EventLogger: ctx.EventLogger(),

Check warning on line 530 in gno.land/pkg/sdk/vm/keeper.go

View check run for this annotation

Codecov / codecov/patch

gno.land/pkg/sdk/vm/keeper.go#L530

Added line #L530 was not covered by tests
}
m := gno.NewMachineWithOptions(
gno.MachineOptions{
Expand Down
25 changes: 25 additions & 0 deletions gnovm/stdlibs/native.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions gnovm/stdlibs/std/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ type ExecContext struct {
OrigSend std.Coins
OrigSendSpent *std.Coins // mutable
Banker BankerInterface
EventLogger *sdk.EventLogger
}
14 changes: 14 additions & 0 deletions gnovm/stdlibs/std/emit_event.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package std

// Emit is a function that constructs a GnoEvent with a specified type and attributes.
// It then forwards this event to the event logger. Each emitted event carries metadata
// such as the timestamp of emission, the event type, and the provided attributes.
notJoon marked this conversation as resolved.
Show resolved Hide resolved
//
// The function takes arguments in pairs. The first element of each pair is considered
// the attribute key, and the second element is the corresponding value.
notJoon marked this conversation as resolved.
Show resolved Hide resolved
//
// The event is dispatched to the EventLogger, which resides in the tm2/pkg/sdk/events.go file.
//
// For more details about the GnoEvent data structure, refer to its definition in the emit_event.go file.
func Emit(typ string, attrs ...string) { emit(typ, attrs) }
func emit(typ string, attrs []string)
77 changes: 77 additions & 0 deletions gnovm/stdlibs/std/emit_event.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package std

// ref: https://github.com/gnolang/gno/pull/853
notJoon marked this conversation as resolved.
Show resolved Hide resolved

import (
"encoding/json"
"errors"

gno "github.com/gnolang/gno/gnovm/pkg/gnolang"
abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types"
)

func X_emit(m *gno.Machine, typ string, attrs []string) {
eventAttrs, err := attrKeysAndValues(attrs)
if err != nil {
m.Panic(typedString(err.Error()))
}

pkgPath := CurrentRealmPath(m)
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved
fnIdent := getPrevFunctionNameFromTarget(m, "Emit")
timestamp := getTimestamp(m)

evtstr := NewGnoEventString(typ, pkgPath, fnIdent, timestamp, eventAttrs...)
ctx := m.Context.(ExecContext)
ctx.EventLogger.EmitEvent(evtstr)
}

func attrKeysAndValues(attrs []string) ([]gnoEventAttribute, error) {
attrLen := len(attrs)
if attrLen%2 != 0 {
return nil, errors.New("odd number of attributes. cannot create key-value pairs")
notJoon marked this conversation as resolved.
Show resolved Hide resolved
}
eventAttrs := make([]gnoEventAttribute, attrLen/2)
for i := 0; i < attrLen-1; i += 2 {
eventAttrs[i/2] = gnoEventAttribute{
Key: attrs[i],
Value: attrs[i+1],
}
}
return eventAttrs, nil
}

type temp gnoEvent
notJoon marked this conversation as resolved.
Show resolved Hide resolved

func NewGnoEventString(eventType, pkgPath, ident string, timestamp int64, attrs ...gnoEventAttribute) abci.EventString {
evt := newGnoEvent(eventType, pkgPath, ident, timestamp, attrs...)

jsonRes, err := json.Marshal(map[string]temp{evt.Type: temp(*evt)})
if err != nil {
panic(err)
}

return abci.EventString(jsonRes)
}

type gnoEvent struct {
Type string `json:"-"`
notJoon marked this conversation as resolved.
Show resolved Hide resolved
PkgPath string `json:"pkg_path"`
Identifier string `json:"identifier"`
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved
Timestamp int64 `json:"timestamp"`
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved
Attributes []gnoEventAttribute `json:"attributes"`
}

func newGnoEvent(eventType string, pkgPath string, ident string, timestamp int64, attrs ...gnoEventAttribute) *gnoEvent {
return &gnoEvent{
Type: eventType,
PkgPath: pkgPath,
Identifier: ident,
Attributes: attrs,
Timestamp: timestamp,
notJoon marked this conversation as resolved.
Show resolved Hide resolved
}
}

type gnoEventAttribute struct {
Key string `json:"key"`
Value string `json:"value"`
}
14 changes: 14 additions & 0 deletions gnovm/stdlibs/std/native.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,20 @@ func GetHeight(m *gno.Machine) int64 {
return m.Context.(ExecContext).Height
}

func getTimestamp(m *gno.Machine) int64 {
return m.Context.(ExecContext).Timestamp
}

// getPrevFunctionNameFromTarget returns the last called function name (identifier) from the call stack.
func getPrevFunctionNameFromTarget(m *gno.Machine, targetFunc string) string {
for i := 0; i < len(m.Frames); i++ {
if m.Frames[i].Func.Name == gno.Name(targetFunc) && i > 0 {
notJoon marked this conversation as resolved.
Show resolved Hide resolved
return string(m.Frames[i-1].Func.Name)
}
}
return ""
}

func X_origSend(m *gno.Machine) (denoms []string, amounts []int64) {
os := m.Context.(ExecContext).OrigSend
return ExpandCoins(os)
Expand Down
19 changes: 19 additions & 0 deletions gnovm/stdlibs/std/package.go
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package std

import (
"github.com/gnolang/gno/tm2/pkg/amino"
abci "github.com/gnolang/gno/tm2/pkg/bft/abci/types"
)

var Package = amino.RegisterPackage(amino.NewPackage(
moul marked this conversation as resolved.
Show resolved Hide resolved
"github.com/gnolang/gno/gnovm/stdlibs/std",
"tm",
amino.GetCallersDirname(),
).
WithDependencies(
abci.Package,
).
WithTypes(
gnoEventAttribute{},
gnoEvent{},
))
2 changes: 2 additions & 0 deletions gnovm/tests/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/gnolang/gno/gnovm/stdlibs"
"github.com/gnolang/gno/tm2/pkg/crypto"
osm "github.com/gnolang/gno/tm2/pkg/os"
"github.com/gnolang/gno/tm2/pkg/sdk"
"github.com/gnolang/gno/tm2/pkg/std"
"github.com/pmezard/go-difflib/difflib"
)
Expand Down Expand Up @@ -50,6 +51,7 @@ func testMachineCustom(store gno.Store, pkgPath string, stdout io.Writer, maxAll
OrigSend: send,
OrigSendSpent: new(std.Coins),
Banker: banker,
EventLogger: sdk.NewEventLogger(),
}
m := gno.NewMachineWithOptions(gno.MachineOptions{
PkgPath: "", // set later.
Expand Down
2 changes: 1 addition & 1 deletion gnovm/tests/files/zrealm_natbind0.gno
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ func main() {
// "Closure": {
// "@type": "/gno.RefValue",
// "Escaped": true,
// "ObjectID": "a7f5397443359ea76c50be82c77f1f893a060925:6"
// "ObjectID": "a7f5397443359ea76c50be82c77f1f893a060925:7"
// },
// "FileName": "native.gno",
// "IsMethod": false,
Expand Down
9 changes: 9 additions & 0 deletions tm2/pkg/bft/abci/types/types.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package abci

import (
"encoding/json"
"time"

"github.com/gnolang/gno/tm2/pkg/crypto"
Expand Down Expand Up @@ -116,6 +117,14 @@ func (r ResponseBase) IsErr() bool {
return r.Error != nil
}

func (r ResponseBase) EncodeEvent() []byte {
notJoon marked this conversation as resolved.
Show resolved Hide resolved
res, err := json.Marshal(r.Events)
if err != nil {
return nil
zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved
}
return res
}

// nondeterministic
type ResponseException struct {
ResponseBase
Expand Down
3 changes: 2 additions & 1 deletion tm2/pkg/crypto/keys/client/maketx.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,8 @@ func ExecSignAndBroadcast(
io.Println(string(bres.DeliverTx.Data))
io.Println("OK!")
io.Println("GAS WANTED:", bres.DeliverTx.GasWanted)
io.Println("GAS USED: ", bres.DeliverTx.GasUsed)
io.Println("GAS USED:", bres.DeliverTx.GasUsed)
io.Println("EVENTS:", string(bres.DeliverTx.EncodeEvent()))

zivkovicmilos marked this conversation as resolved.
Show resolved Hide resolved
return nil
}
1 change: 1 addition & 0 deletions tm2/pkg/sdk/baseapp.go
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,7 @@ func (app *BaseApp) runMsgs(ctx Context, msgs []Msg, mode RunTxMode) (result Res
// each result.
data = append(data, msgResult.Data...)
events = append(events, msgResult.Events...)
events = append(events, ctx.EventLogger().Events()...)
notJoon marked this conversation as resolved.
Show resolved Hide resolved
// TODO append msgevent from ctx. XXX XXX

// stop execution and return on first failed message
Expand Down
2 changes: 1 addition & 1 deletion tm2/pkg/sdk/sdk.proto
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ message Result {
abci.ResponseBase response_base = 1 [json_name = "ResponseBase"];
sint64 gas_wanted = 2 [json_name = "GasWanted"];
sint64 gas_used = 3 [json_name = "GasUsed"];
}
}
Loading