diff --git a/.github/workflows/fossa.yml b/.github/workflows/fossa.yml index 11f04ca8282..9de8d536b29 100644 --- a/.github/workflows/fossa.yml +++ b/.github/workflows/fossa.yml @@ -31,7 +31,7 @@ jobs: uses: coursier/cache-action@v6.4.6 - name: Set up JDK 17 - uses: coursier/setup-action@v1.3.5 + uses: coursier/setup-action@v1.3.6 with: jvm: temurin:1.17 diff --git a/contribs/gnodev/cmd/gnobro/main.go b/contribs/gnodev/cmd/gnobro/main.go index 6bb6bfc2396..092a441542a 100644 --- a/contribs/gnodev/cmd/gnobro/main.go +++ b/contribs/gnodev/cmd/gnobro/main.go @@ -5,6 +5,7 @@ import ( "errors" "flag" "fmt" + "io" "log/slog" "net" "net/url" @@ -21,7 +22,6 @@ import ( "github.com/charmbracelet/wish" "github.com/charmbracelet/wish/activeterm" "github.com/charmbracelet/wish/bubbletea" - "github.com/charmbracelet/wish/logging" "golang.org/x/sync/errgroup" "github.com/gnolang/gno/contribs/gnodev/pkg/browser" @@ -47,6 +47,7 @@ type broCfg struct { sshListener string sshHostKeyPath string banner bool + jsonlog bool } var defaultBroOptions = broCfg{ @@ -152,6 +153,13 @@ func (c *broCfg) RegisterFlags(fs *flag.FlagSet) { defaultBroOptions.readonly, "readonly mode, no commands allowed", ) + + fs.BoolVar( + &c.jsonlog, + "jsonlog", + defaultBroOptions.jsonlog, + "display server log as json format", + ) } func execBrowser(cfg *broCfg, args []string, cio commands.IO) error { @@ -277,9 +285,7 @@ func runLocal(ctx context.Context, gnocl *gnoclient.Client, cfg *broCfg, bcfg br func runServer(ctx context.Context, gnocl *gnoclient.Client, cfg *broCfg, bcfg browser.Config, io commands.IO) error { // setup logger - charmlogger := charmlog.New(io.Out()) - charmlogger.SetLevel(charmlog.DebugLevel) - logger := slog.New(charmlogger) + logger := newLogger(io.Out(), cfg.jsonlog) teaHandler := func(s ssh.Session) (tea.Model, []tea.ProgramOption) { shortid := fmt.Sprintf("%.10s", s.Context().SessionID()) @@ -326,8 +332,8 @@ func runServer(ctx context.Context, gnocl *gnoclient.Client, cfg *broCfg, bcfg b bubbletea.Middleware(teaHandler), activeterm.Middleware(), // ensure PTY ValidatePathCommandMiddleware(bcfg.URLPrefix), - logging.StructuredMiddlewareWithLogger( - charmlogger, charmlog.DebugLevel, + StructuredMiddlewareWithLogger( + ctx, logger, slog.LevelInfo, ), // XXX: add ip throttler ), @@ -358,7 +364,9 @@ func runServer(ctx context.Context, gnocl *gnoclient.Client, cfg *broCfg, bcfg b return err } - io.Println("Bye!") + if !cfg.jsonlog { + io.Println("Bye!") + } return nil } @@ -460,3 +468,47 @@ func ValidatePathCommandMiddleware(pathPrefix string) wish.Middleware { } } } + +func StructuredMiddlewareWithLogger(ctx context.Context, logger *slog.Logger, level slog.Level) wish.Middleware { + return func(next ssh.Handler) ssh.Handler { + return func(sess ssh.Session) { + ct := time.Now() + hpk := sess.PublicKey() != nil + pty, _, _ := sess.Pty() + logger.Log( + ctx, + level, + "connect", + "user", sess.User(), + "remote-addr", sess.RemoteAddr().String(), + "public-key", hpk, + "command", sess.Command(), + "term", pty.Term, + "width", pty.Window.Width, + "height", pty.Window.Height, + "client-version", sess.Context().ClientVersion(), + ) + next(sess) + logger.Log( + ctx, + level, + "disconnect", + "user", sess.User(), + "remote-addr", sess.RemoteAddr().String(), + "duration", time.Since(ct), + ) + } + } +} + +func newLogger(out io.Writer, json bool) *slog.Logger { + if json { + return slog.New(slog.NewJSONHandler(out, &slog.HandlerOptions{ + Level: slog.LevelDebug, + })) + } + + charmlogger := charmlog.New(out) + charmlogger.SetLevel(charmlog.DebugLevel) + return slog.New(charmlogger) +} diff --git a/contribs/gnofaucet/README.md b/contribs/gnofaucet/README.md new file mode 100644 index 00000000000..eefa41a8c6f --- /dev/null +++ b/contribs/gnofaucet/README.md @@ -0,0 +1,25 @@ +# Start a local faucet + +## Step1: + +Make sure you have started gnoland + + ../../gno.land/build/gnoland start -lazy + +## Step2: + +Start the faucet. + + ./build/gnofaucet serve -chain-id dev -mnemonic "source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast" + +By default, the faucet sends out 10,000,000ugnot (10gnot) per request. + +## Step3: + +Make sure you have started website + + ../../gno.land/build/gnoweb + +Request testing tokens from following URL, Have fun! + + http://localhost:8888/faucet \ No newline at end of file diff --git a/docs/reference/gno-js-client/gno-provider.md b/docs/reference/gno-js-client/gno-provider.md index df808106cc3..1b9cbd53652 100644 --- a/docs/reference/gno-js-client/gno-provider.md +++ b/docs/reference/gno-js-client/gno-provider.md @@ -116,7 +116,7 @@ Returns **Promise** #### Usage ```ts -await provider.getFileContent('gno.land/r/demo/foo20', 'TotalSupply()') +await provider.getFileContent('gno.land/r/demo/foo20') /* foo20.gno foo20_test.gno diff --git a/examples/gno.land/p/demo/fqname/fqname.gno b/examples/gno.land/p/demo/fqname/fqname.gno index a877a041ef9..d28453e5c1b 100644 --- a/examples/gno.land/p/demo/fqname/fqname.gno +++ b/examples/gno.land/p/demo/fqname/fqname.gno @@ -47,6 +47,7 @@ func Parse(fqname string) (pkgpath, name string) { // fmt.Println("Fully Qualified Name:", fqName) // // Output: gno.land/r/demo/foo20.GRC20 func Construct(pkgpath, name string) string { + // TODO: ensure pkgpath is valid - and as such last part does not contain a dot. if name == "" { return pkgpath } diff --git a/examples/gno.land/p/moul/printfdebugging/color.gno b/examples/gno.land/p/moul/printfdebugging/color.gno new file mode 100644 index 00000000000..b3bf647b9b5 --- /dev/null +++ b/examples/gno.land/p/moul/printfdebugging/color.gno @@ -0,0 +1,81 @@ +package printfdebugging + +// consts copied from https://github.com/fatih/color/blob/main/color.go + +// Attribute defines a single SGR Code +type Attribute int + +const Escape = "\x1b" + +// Base attributes +const ( + Reset Attribute = iota + Bold + Faint + Italic + Underline + BlinkSlow + BlinkRapid + ReverseVideo + Concealed + CrossedOut +) + +const ( + ResetBold Attribute = iota + 22 + ResetItalic + ResetUnderline + ResetBlinking + _ + ResetReversed + ResetConcealed + ResetCrossedOut +) + +// Foreground text colors +const ( + FgBlack Attribute = iota + 30 + FgRed + FgGreen + FgYellow + FgBlue + FgMagenta + FgCyan + FgWhite +) + +// Foreground Hi-Intensity text colors +const ( + FgHiBlack Attribute = iota + 90 + FgHiRed + FgHiGreen + FgHiYellow + FgHiBlue + FgHiMagenta + FgHiCyan + FgHiWhite +) + +// Background text colors +const ( + BgBlack Attribute = iota + 40 + BgRed + BgGreen + BgYellow + BgBlue + BgMagenta + BgCyan + BgWhite +) + +// Background Hi-Intensity text colors +const ( + BgHiBlack Attribute = iota + 100 + BgHiRed + BgHiGreen + BgHiYellow + BgHiBlue + BgHiMagenta + BgHiCyan + BgHiWhite +) diff --git a/examples/gno.land/p/moul/printfdebugging/gno.mod b/examples/gno.land/p/moul/printfdebugging/gno.mod new file mode 100644 index 00000000000..2cf6aa09e61 --- /dev/null +++ b/examples/gno.land/p/moul/printfdebugging/gno.mod @@ -0,0 +1,3 @@ +module gno.land/p/demo/printfdebugging + +require gno.land/p/demo/ufmt v0.0.0-latest diff --git a/examples/gno.land/p/moul/printfdebugging/printfdebugging.gno b/examples/gno.land/p/moul/printfdebugging/printfdebugging.gno new file mode 100644 index 00000000000..a12a3dfadd2 --- /dev/null +++ b/examples/gno.land/p/moul/printfdebugging/printfdebugging.gno @@ -0,0 +1,19 @@ +// this package is a joke... or not. +package printfdebugging + +import ( + "strings" + + "gno.land/p/demo/ufmt" +) + +func BigRedLine(args ...string) { + println(ufmt.Sprintf("%s[%dm####################################%s[%dm %s", + Escape, int(BgRed), Escape, int(Reset), + strings.Join(args, " "), + )) +} + +func Success() { + println(" \033[31mS\033[33mU\033[32mC\033[36mC\033[34mE\033[35mS\033[31mS\033[0m ") +} diff --git a/examples/gno.land/r/demo/boards/README.md b/examples/gno.land/r/demo/boards/README.md index a9b68ec9c92..628bc9aa349 100644 --- a/examples/gno.land/r/demo/boards/README.md +++ b/examples/gno.land/r/demo/boards/README.md @@ -58,7 +58,8 @@ your `ACCOUNT_ADDR` and `KEYNAME` Instead of editing `gno.land/genesis/genesis_balances.txt`, a more general solution (with more steps) is to run a local "faucet" and use the web browser to add $GNOT. (This can be done at any time.) -See this page: https://github.com/gnolang/gno/blob/master/gno.land/cmd/gnofaucet/README.md +See this page: https://github.com/gnolang/gno/blob/master/contribs/gnofaucet/README.md + ### Start the `gnoland` node. diff --git a/examples/gno.land/r/demo/counter/counter.gno b/examples/gno.land/r/demo/counter/counter.gno new file mode 100644 index 00000000000..43943e114dc --- /dev/null +++ b/examples/gno.land/r/demo/counter/counter.gno @@ -0,0 +1,14 @@ +package counter + +import "strconv" + +var counter int + +func Increment() int { + counter++ + return counter +} + +func Render(_ string) string { + return strconv.Itoa(counter) +} diff --git a/examples/gno.land/r/demo/counter/counter_test.gno b/examples/gno.land/r/demo/counter/counter_test.gno new file mode 100644 index 00000000000..352889f7e59 --- /dev/null +++ b/examples/gno.land/r/demo/counter/counter_test.gno @@ -0,0 +1,22 @@ +package counter + +import "testing" + +func TestIncrement(t *testing.T) { + counter = 0 + val := Increment() + if val != 1 { + t.Fatalf("result from Increment(): %d != 1", val) + } + if counter != val { + t.Fatalf("counter (%d) != val (%d)", counter, val) + } +} + +func TestRender(t *testing.T) { + counter = 1337 + res := Render("") + if res != "1337" { + t.Fatalf("render result %q != %q", res, "1337") + } +} diff --git a/examples/gno.land/r/demo/counter/gno.mod b/examples/gno.land/r/demo/counter/gno.mod new file mode 100644 index 00000000000..332d4e6da6a --- /dev/null +++ b/examples/gno.land/r/demo/counter/gno.mod @@ -0,0 +1 @@ +module gno.land/r/demo/counter diff --git a/tm2/pkg/bft/fail/fail.go b/tm2/pkg/bft/fail/fail.go index 607084f484f..c56f43d7d89 100644 --- a/tm2/pkg/bft/fail/fail.go +++ b/tm2/pkg/bft/fail/fail.go @@ -4,31 +4,33 @@ import ( "fmt" "os" "strconv" + "sync" ) -func envSet() int { +func setFromEnv() { callIndexToFailS := os.Getenv("FAIL_TEST_INDEX") if callIndexToFailS == "" { - return -1 + callIndexToFail = -1 } else { var err error - callIndexToFail, err := strconv.Atoi(callIndexToFailS) + callIndexToFail, err = strconv.Atoi(callIndexToFailS) if err != nil { - return -1 + callIndexToFail = -1 } - return callIndexToFail } } -// Fail when FAIL_TEST_INDEX == callIndex -var callIndex int // indexes Fail calls +var ( + callIndex int // indexes Fail calls + callIndexToFail int // index of call which should fail + callIndexToFailOnce sync.Once // sync.Once to set the value of the above +) +// Fail exits the program when after being called the same number of times as +// that passed as the FAIL_TEST_INDEX environment variable. func Fail() { - callIndexToFail := envSet() - if callIndexToFail < 0 { - return - } + callIndexToFailOnce.Do(setFromEnv) if callIndex == callIndexToFail { Exit() diff --git a/tm2/pkg/sdk/baseapp.go b/tm2/pkg/sdk/baseapp.go index 867a38d680a..671f18cf058 100644 --- a/tm2/pkg/sdk/baseapp.go +++ b/tm2/pkg/sdk/baseapp.go @@ -625,11 +625,12 @@ func (app *BaseApp) runMsgs(ctx Context, msgs []Msg, mode RunTxMode) (result Res ctx = ctx.WithEventLogger(NewEventLogger()) msgLogs := make([]string, 0, len(msgs)) - data := make([]byte, 0, len(msgs)) - err := error(nil) - events := []Event{} + var ( + err error + events = []Event{} + ) // NOTE: GasWanted is determined by ante handler and GasUsed by the GasMeter. for i, msg := range msgs { @@ -660,6 +661,7 @@ func (app *BaseApp) runMsgs(ctx Context, msgs []Msg, mode RunTxMode) (result Res fmt.Sprintf("msg:%d,success:%v,log:%s,events:%v", i, false, msgResult.Log, events)) err = msgResult.Error + events = nil break } @@ -667,7 +669,10 @@ func (app *BaseApp) runMsgs(ctx Context, msgs []Msg, mode RunTxMode) (result Res fmt.Sprintf("msg:%d,success:%v,log:%s,events:%v", i, true, msgResult.Log, events)) } - events = append(events, ctx.EventLogger().Events()...) + + if err == nil { + events = append(events, ctx.EventLogger().Events()...) + } result.Error = ABCIError(err) result.Data = data