From 5a8476e16101f95148a49589d6f662a27ae9bc31 Mon Sep 17 00:00:00 2001 From: Morgan Bazalgette Date: Wed, 29 Nov 2023 21:05:06 +0100 Subject: [PATCH 01/13] feat: split packages, add better devnet deployment system --- .dockerignore | 2 + .gitignore | 3 + docker-compose.yml | 20 +- realm/rules.gno => package/engine.gno | 27 +- .../rules_test.gno => package/engine_test.gno | 0 package/gno.mod | 7 + package/zobrist/gno.mod | 1 + {util => package/zobrist}/rands.go | 0 realm/hash.gno => package/zobrist/zobrist.gno | 56 +- package/zobrist/zobrist_test.gno | 55 + realm/chess.gno | 85 +- realm/chess_test.gno | 9 +- realm/glicko2.gno | 1 + realm/glicko2_test.gno | 6 +- realm/gno.mod | 1 + .../raffle/GOPHERCON_COMPETITION.md | 0 tutorial/01_getting_started/gno.mod | 2 +- util/devnet/README.md | 23 - util/devnet/deployer/Dockerfile | 9 - util/devnet/deployer/deployer.sh | 26 - util/devnet/docker-compose.yml | 65 - util/gnolanddev/Dockerfile | 25 + util/{devnet => gnolanddev}/config.toml | 2 +- .../pull-1048-assertorigincall.diff | 1964 +++++++++++++++++ util/gnolanddev/run.sh | 26 + util/gnolanddev/strconv/decimal.gno | 415 ++++ util/gnolanddev/strconv/decimal_test.gno | 126 ++ util/gnolanddev/strconv/ftoa.gno | 702 ++++++ util/gnolanddev/strconv/ftoa_test.gno | 275 +++ util/gnolanddev/strconv/ftoaryu.gno | 1280 +++++++++++ util/gnolanddev/strconv/ftoaryu_test.gno | 30 + util/gnolanddev/strconv/internal_test.gno | 21 + 32 files changed, 5058 insertions(+), 206 deletions(-) create mode 100644 .dockerignore rename realm/rules.gno => package/engine.gno (96%) rename realm/rules_test.gno => package/engine_test.gno (100%) create mode 100644 package/gno.mod create mode 100644 package/zobrist/gno.mod rename {util => package/zobrist}/rands.go (100%) rename realm/hash.gno => package/zobrist/zobrist.gno (93%) create mode 100644 package/zobrist/zobrist_test.gno rename GOPHERCON_COMPETITION.md => realm/raffle/GOPHERCON_COMPETITION.md (100%) delete mode 100644 util/devnet/README.md delete mode 100644 util/devnet/deployer/Dockerfile delete mode 100755 util/devnet/deployer/deployer.sh delete mode 100644 util/devnet/docker-compose.yml create mode 100644 util/gnolanddev/Dockerfile rename util/{devnet => gnolanddev}/config.toml (99%) create mode 100644 util/gnolanddev/pull-1048-assertorigincall.diff create mode 100755 util/gnolanddev/run.sh create mode 100644 util/gnolanddev/strconv/decimal.gno create mode 100644 util/gnolanddev/strconv/decimal_test.gno create mode 100644 util/gnolanddev/strconv/ftoa.gno create mode 100644 util/gnolanddev/strconv/ftoa_test.gno create mode 100644 util/gnolanddev/strconv/ftoaryu.gno create mode 100644 util/gnolanddev/strconv/ftoaryu_test.gno create mode 100644 util/gnolanddev/strconv/internal_test.gno diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..e99d0488 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +.tmp +.git diff --git a/.gitignore b/.gitignore index 80ab2c26..bd126f13 100644 --- a/.gitignore +++ b/.gitignore @@ -120,6 +120,9 @@ web/public/**/*.xml realm/*.go +*.gen.go +.*.gen.go +*.gen_test.go *.vim .tmp/ diff --git a/docker-compose.yml b/docker-compose.yml index 9761ae2a..797e5748 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,14 +6,13 @@ volumes: services: gnoland: - image: ghcr.io/gnolang/gno/gnochess:latest + build: ./util/gnolanddev environment: - LOG_LEVEL=4 - command: ["gnoland", "start", "-genesis-max-vm-cycles", "100000000"] volumes: - "gnonode:/opt/gno/src/testdir" - - "./util/devnet/config.toml:/opt/gno/src/gno.land/testdir/config/config.toml" - working_dir: /opt/gno/src/gno.land + - "./util/gnolanddev/config.toml:/opt/gno/src/gno.land/testdir/config/config.toml" + - ".:/mnt" ports: - 26657:26657 restart: on-failure @@ -23,13 +22,13 @@ services: max-file: "10" max-size: "100m" - deployer: - build: ./util/devnet/deployer + gnoweb: + image: ghcr.io/gnolang/gno:latest + working_dir: /opt/gno/src/gno.land + command: gnoweb -bind 0.0.0.0:8888 -remote gnoland:26657 + ports: + - 8888:8888 restart: on-failure - depends_on: - - gnoland - volumes: - - "./realm:/realm" logging: driver: "json-file" options: @@ -95,6 +94,7 @@ services: signup-functions: image: williamjackson/netlify-cli + stop_grace_period: 500ms # XXX: improve by making this a dockerfile which has dumb-init depends_on: - redis command: ["functions:serve", "-f", "./functions", "-p", "9000"] diff --git a/realm/rules.gno b/package/engine.gno similarity index 96% rename from realm/rules.gno rename to package/engine.gno index 30b5f5f5..c931d6e3 100644 --- a/realm/rules.gno +++ b/package/engine.gno @@ -1,9 +1,12 @@ -// This file is focused on elemental types and functions for handling -// chess games. Thus, the move legality rules are implemented here. +// Package chess implements a simple chess engine, designed to implement all +// of the official FIDE rules with the intention of validating moves for a +// "chess server" realm (gno.land/r/demo/chess). // -// To verify the following section, see the FIDE "Laws of Chess": +// To implement the rules, the FIDE "Laws of Chess" are used as a reference: // https://www.fide.com/FIDE/handbook/LawsOfChess.pdf - +// +// This package was designed with a focus on clarity and on using this code as +// a didactic tool. Any contributions to the code should respect this. package chess import ( @@ -11,6 +14,8 @@ import ( "sort" "strconv" "strings" + + "gno.land/p/demo/chess/zobrist" ) // PositionFlags. The lower 4 bits indicate an en passant column; the upper @@ -51,6 +56,8 @@ func (p PositionFlags) CastlingRights() string { // Position contains the information about a chessboard, and surrounding // context: the previous moves, the castling rights and "en passant" column. +// +// NOTE: the position of a piece is encoded in a [Square]. type Position struct { B Board Moves []Move @@ -70,7 +77,7 @@ func NewPosition() Position { return Position{ B: NewBoard(), Moves: make([]Move, 0, 80), // typical chess game is ~40 moves, 80 half-moves - Hashes: []uint64{hashInitialPosition}, + Hashes: []uint64{zobrist.InitialPosition}, } } @@ -206,6 +213,7 @@ func (p Position) ValidateMove(m Move) (newP Position, valid bool) { // validateMove allows for m to be a "king-capture" move, which is illegal in // chess, but it is useful for InCheck. +// This is commonly known in chess programming as a "pseudo-legal" move. func (oldp Position) validateMove(m Move) (_ Position, ok bool) { p := oldp.clone() @@ -447,7 +455,7 @@ func (oldp Position) validateMove(m Move) (_ Position, ok bool) { p.Hashes, // color is inverted, because we consider the present move as already // done (hence, it is the other player to move). - zobrist(p.B, bool(!color), byte(p.Flags)>>4, ep), + zobrist.Hash(zobrist.Board(p.B), bool(!color), byte(p.Flags)>>4, ep), ) // is our king in check, as a result of the current move? @@ -958,6 +966,13 @@ func (c Color) Piece() Piece { // Piece represents a piece on the board. type Piece byte +// PieceFromChar returns the piece corresponding to the given character. +// White pieces are uppercase, and black pieces are lowercase. +// If a piece is invalid, PieceInvalid is returned. +func PieceFromChar(b byte) Piece { + return p[b] +} + // piece character to internal piece var p = [256]Piece{ 'P': PiecePawn, diff --git a/realm/rules_test.gno b/package/engine_test.gno similarity index 100% rename from realm/rules_test.gno rename to package/engine_test.gno diff --git a/package/gno.mod b/package/gno.mod new file mode 100644 index 00000000..7b25435c --- /dev/null +++ b/package/gno.mod @@ -0,0 +1,7 @@ +module gno.land/p/demo/chess + +require ( + gno.land/p/demo/chess/zobrist v0.0.0-latest +) + +replace gno.land/p/demo/chess/zobrist => ./zobrist diff --git a/package/zobrist/gno.mod b/package/zobrist/gno.mod new file mode 100644 index 00000000..aa67db18 --- /dev/null +++ b/package/zobrist/gno.mod @@ -0,0 +1 @@ +module gno.land/p/demo/chess/zobrist diff --git a/util/rands.go b/package/zobrist/rands.go similarity index 100% rename from util/rands.go rename to package/zobrist/rands.go diff --git a/realm/hash.gno b/package/zobrist/zobrist.gno similarity index 93% rename from realm/hash.gno rename to package/zobrist/zobrist.gno index 17e47d8d..393d9d30 100644 --- a/realm/hash.gno +++ b/package/zobrist/zobrist.gno @@ -1,25 +1,44 @@ -// this file contains an implementation of Zobrist Hashing +// Package zobrist contains an implementation of the Zobrist Hashing algorithm. // https://www.chessprogramming.org/Zobrist_Hashing +// +// The hash is performed using a series of random numbers generated through +// rands.go, in this source directory. +package zobrist -package chess +// Board is a representation of a chess board. +// Details on how to transform a chess algebraic position into an index +// can be found at [Square]. +type Board [64]Piece -/* to generate hashInitialPosition -func init() { - println( - "initial position hash", - zobrist( - NewBoard(), - false, - 0, - 255, - ), - ) -} -*/ +// Piece represents a piece on the board. +type Piece byte + +// Possible values of Piece. Within the context of Board, Piece is assumed to +// be white, unless p&PieceBlack != 0. Note PieceBlack is not a valid piece; it +// must be bitwise OR'd to a non-empty piece. +const ( + PieceEmpty Piece = iota + + PiecePawn + PieceRook + PieceKnight + PieceBishop + PieceQueen + PieceKing + + PieceBlack Piece = 8 // bit-flag +) -const hashInitialPosition uint64 = 1957848132405881468 +// InitialPosition is the zobrist hash (as implemented by this package) +// for the initial chess position. +const InitialPosition uint64 = 1957848132405881468 -func zobrist(b Board, isBlack bool, castling, epFile byte) uint64 { +// Hash generates a Zobrist hash with the given parameter. +// +// castling can assume a value between [0,16), +// epFile should be set to a value between [0,8) -- if there is no en passant +// file, pass 255 (as a convention). +func Hash(b Board, isBlack bool, castling, epFile byte) uint64 { var hash uint64 if isBlack { hash ^= hashBlack @@ -28,7 +47,7 @@ func zobrist(b Board, isBlack bool, castling, epFile byte) uint64 { if p == PieceEmpty { continue } - if p.Color() == White { + if p&PieceBlack == 0 { // values 0-5 p-- } else { @@ -44,7 +63,6 @@ func zobrist(b Board, isBlack bool, castling, epFile byte) uint64 { return hash } -// randomly generated using utils/rand.go var ( hashBlack uint64 = 0x331cf7440c179431 hashCastling = [...]uint64{ diff --git a/package/zobrist/zobrist_test.gno b/package/zobrist/zobrist_test.gno new file mode 100644 index 00000000..4a5b97fe --- /dev/null +++ b/package/zobrist/zobrist_test.gno @@ -0,0 +1,55 @@ +package zobrist + +import ( + "testing" +) + +// piece character to internal piece +var p = [256]Piece{ + 'P': PiecePawn, + 'R': PieceRook, + 'N': PieceKnight, + 'B': PieceBishop, + 'Q': PieceQueen, + 'K': PieceKing, + + 'p': PieceBlack | PiecePawn, + 'r': PieceBlack | PieceRook, + 'n': PieceBlack | PieceKnight, + 'b': PieceBlack | PieceBishop, + 'q': PieceBlack | PieceQueen, + 'k': PieceBlack | PieceKing, +} + +// NewBoard returns a Board normally set up at the initial position for standard +// chess. +func NewBoard() Board { + return Board{ + // row 1 + p['R'], p['N'], p['B'], p['Q'], + p['K'], p['B'], p['N'], p['R'], + // row 2 + p['P'], p['P'], p['P'], p['P'], + p['P'], p['P'], p['P'], p['P'], + + // rows 3, 4, 5, 6 + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + // row 7 + p['p'], p['p'], p['p'], p['p'], + p['p'], p['p'], p['p'], p['p'], + // row 8 + p['r'], p['n'], p['b'], p['q'], + p['k'], p['b'], p['n'], p['r'], + } +} + +func TestInitialPosition(t *testing.T) { + h := Hash(NewBoard(),false, 0, 255) + if h != InitialPosition { + t.Fatalf("InitialPosition is invalid: set to %d, should be %d", InitialPosition, h) + } +} diff --git a/realm/chess.gno b/realm/chess.gno index 52a09d21..550dee08 100644 --- a/realm/chess.gno +++ b/realm/chess.gno @@ -9,6 +9,7 @@ import ( "time" "gno.land/p/demo/avl" + "gno.land/p/demo/chess" "gno.land/p/demo/ufmt" ) @@ -26,11 +27,11 @@ var ( type Game struct { ID string `json:"id"` - White std.Address `json:"white"` - Black std.Address `json:"black"` - Position Position `json:"position"` - State GameState `json:"state"` - Winner Winner `json:"winner"` + White std.Address `json:"white"` + Black std.Address `json:"black"` + Position chess.Position `json:"position"` + State GameState `json:"state"` + Winner Winner `json:"winner"` Creator std.Address `json:"creator"` CreatedAt time.Time `json:"created_at"` @@ -56,12 +57,12 @@ func (g Game) MarshalJSON() (_ []byte, err error) { } return `"` + na.String() + `"` } - mjson := func(s string, val interface{ MarshalJSON() ([]byte, error) }, comma bool) { + mjson := func(s string, val func() ([]byte, error), comma bool) { if err != nil { return } var res []byte - res, err = val.MarshalJSON() + res, err = val() if err != nil { return } @@ -76,9 +77,9 @@ func (g Game) MarshalJSON() (_ []byte, err error) { b.WriteString(`"white":"` + g.White.String() + `",`) b.WriteString(`"black":"` + g.Black.String() + `",`) - mjson("position", g.Position, true) - mjson("state", g.State, true) - mjson("winner", g.Winner, true) + mjson("position", marshalPosition(g.Position), true) + mjson("state", g.State.MarshalJSON, true) + mjson("winner", g.Winner.MarshalJSON, true) if err != nil { return } @@ -88,7 +89,7 @@ func (g Game) MarshalJSON() (_ []byte, err error) { b.WriteString(`"draw_offerer":` + nilAddr(g.DrawOfferer) + ",") b.WriteString(`"concluder":` + nilAddr(g.Concluder) + ",") - mjson("time", g.Time, false) + mjson("time", g.Time.MarshalJSON, false) if err != nil { return } @@ -97,25 +98,27 @@ func (g Game) MarshalJSON() (_ []byte, err error) { return b.Bytes(), nil } -func (p Position) MarshalJSON() ([]byte, error) { - var b bytes.Buffer - b.WriteByte('{') +func marshalPosition(p chess.Position) func() ([]byte, error) { + return func() ([]byte, error) { + var b bytes.Buffer + b.WriteByte('{') - bfen := p.EncodeFEN() - b.WriteString(`"fen":"` + bfen + `",`) + bfen := p.EncodeFEN() + b.WriteString(`"fen":"` + bfen + `",`) - b.WriteString(`"moves":[`) + b.WriteString(`"moves":[`) - for idx, m := range p.Moves { - b.WriteString(`"` + m.String() + `"`) - if idx != len(p.Moves)-1 { - b.WriteByte(',') + for idx, m := range p.Moves { + b.WriteString(`"` + m.String() + `"`) + if idx != len(p.Moves)-1 { + b.WriteByte(',') + } } - } - b.WriteByte(']') - b.WriteByte('}') - return b.Bytes(), nil + b.WriteByte(']') + b.WriteByte('}') + return b.Bytes(), nil + } } // Winner represents the "direct" outcome of a game @@ -267,7 +270,7 @@ func newGame(caller, opponent std.Address, seconds, increment int) *Game { ID: id, White: caller, Black: opponent, - Position: NewPosition(), + Position: chess.NewPosition(), State: GameStateOpen, Creator: caller, CreatedAt: time.Now(), @@ -351,7 +354,7 @@ func getGame(id string, wantOpen bool) *Game { // If the piece is a pawn which is moving to the last row, a promotion piece // must be specified. // Castling is specified by indicating the king's movement. -func MakeMove(gameID, from, to string, promote Piece) string { +func MakeMove(gameID, from, to string, promote chess.Piece) string { std.AssertOriginCall() g := getGame(gameID, true) @@ -388,14 +391,14 @@ func MakeMove(gameID, from, to string, promote Piece) string { } // validate move - m := Move{ - From: SquareFromString(from), - To: SquareFromString(to), + m := chess.Move{ + From: chess.SquareFromString(from), + To: chess.SquareFromString(to), } - if m.From == SquareInvalid || m.To == SquareInvalid { + if m.From == chess.SquareInvalid || m.To == chess.SquareInvalid { panic("invalid from/to square") } - if promote > 0 && promote <= PieceKing { + if promote > 0 && promote <= chess.PieceKing { m.Promotion = promote } newp, ok := g.Position.ValidateMove(m) @@ -407,7 +410,7 @@ func MakeMove(gameID, from, to string, promote Piece) string { g.Position = newp o := newp.IsFinished() - if o == NotFinished { + if o == chess.NotFinished { // opponent of draw offerer has made a move. take as implicit rejection of draw. if g.DrawOfferer != nil && *g.DrawOfferer != caller { g.DrawOfferer = nil @@ -417,20 +420,20 @@ func MakeMove(gameID, from, to string, promote Piece) string { } switch { - case o == Checkmate && isBlack: + case o == chess.Checkmate && isBlack: g.State = GameStateCheckmated g.Winner = WinnerBlack - case o == Checkmate && !isBlack: + case o == chess.Checkmate && !isBlack: g.State = GameStateCheckmated g.Winner = WinnerWhite - case o == Stalemate: + case o == chess.Stalemate: g.State = GameStateStalemate g.Winner = WinnerDraw - case o == Drawn75Move: + case o == chess.Drawn75Move: g.State = GameStateDrawn75Move g.Winner = WinnerDraw - case o == Drawn5Fold: + case o == chess.Drawn5Fold: g.State = GameStateDrawn5Fold g.Winner = WinnerDraw } @@ -615,11 +618,11 @@ func Draw(gameID string) string { o := g.Position.IsFinished() switch { - case o&Can50Move != 0: + case o&chess.Can50Move != 0: g.State = GameStateDrawn50Move - case o&Can3Fold != 0: + case o&chess.Can3Fold != 0: g.State = GameStateDrawn3Fold - case o&CanInsufficient != 0: + case o&chess.CanInsufficient != 0: g.State = GameStateDrawnInsufficient default: panic("this game can't be automatically drawn") diff --git a/realm/chess_test.gno b/realm/chess_test.gno index a0543ef8..337f389b 100644 --- a/realm/chess_test.gno +++ b/realm/chess_test.gno @@ -11,6 +11,7 @@ import ( "internal/os_test" "gno.land/p/demo/avl" + "gno.land/p/demo/chess" ) func cleanup() { @@ -290,7 +291,7 @@ func (tc *testCommandNewGame) Run(t *testing.T, bufs map[string]string) { type testCommandMove struct { addr std.Address from, to string - promotion Piece + promotion chess.Piece } func (tc *testCommandMove) Run(t *testing.T, bufs map[string]string) { @@ -418,10 +419,10 @@ func parseCommandTest(t *testing.T, command string) (funcs []testCommandRunner, panic("invalid lan move " + command[2]) } from, to := command[2][:2], command[2][2:4] - var promotion Piece + var promotion chess.Piece if len(command[2]) == 5 { - promotion = p[command[2][4]] - if promotion == PieceEmpty { + promotion = chess.PieceFromChar(command[2][4]) + if promotion == chess.PieceEmpty { panic("invalid piece for promotion: " + string(command[2][4])) } } diff --git a/realm/glicko2.gno b/realm/glicko2.gno index c565b536..edcdba4e 100644 --- a/realm/glicko2.gno +++ b/realm/glicko2.gno @@ -4,6 +4,7 @@ import ( "bytes" "math" "std" + "strconv" ) diff --git a/realm/glicko2_test.gno b/realm/glicko2_test.gno index 2ca2c06e..64e2089d 100644 --- a/realm/glicko2_test.gno +++ b/realm/glicko2_test.gno @@ -21,5 +21,9 @@ func TestExampleCalculations(t *testing.T) { {White: "1", Black: "4", Score: 0}, } updateRatings(ratings, scores) - t.Logf("%+v\n", ratings[0]) + r := ratings[0] + t.Logf("%.4f (± %.4f, volatility: %.4f); working values: %.2f / %.2f / %.2f\n", + r.Rating, r.RatingDeviation, r.RatingVolatility, + r.wr, r.wrd, r.wrv, + ) } diff --git a/realm/gno.mod b/realm/gno.mod index 02204d98..f07b5f13 100644 --- a/realm/gno.mod +++ b/realm/gno.mod @@ -2,6 +2,7 @@ module gno.land/r/demo/chess require ( "gno.land/p/demo/avl" v0.0.0-latest + "gno.land/p/demo/chess" v0.0.0-latest "gno.land/p/demo/ufmt" v0.0.0-latest "gno.land/r/demo/users" v0.0.0-latest ) diff --git a/GOPHERCON_COMPETITION.md b/realm/raffle/GOPHERCON_COMPETITION.md similarity index 100% rename from GOPHERCON_COMPETITION.md rename to realm/raffle/GOPHERCON_COMPETITION.md diff --git a/tutorial/01_getting_started/gno.mod b/tutorial/01_getting_started/gno.mod index b1d10c52..cee66b96 100644 --- a/tutorial/01_getting_started/gno.mod +++ b/tutorial/01_getting_started/gno.mod @@ -1 +1 @@ -module gno.land/r/demo/001_getting_started +module gno.land/r/demo/x01_getting_started diff --git a/util/devnet/README.md b/util/devnet/README.md deleted file mode 100644 index 6e2a0872..00000000 --- a/util/devnet/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# devnet dockerfiles - -Quickly set up a Gnochess devnet & hack interactively! - -Instructions: - -1. Install [`docker`](https://docs.docker.com/engine/install/) and [`docker compose`](https://docs.docker.com/compose/install/) -2. `cd` into this directory from your terminal -3. `docker compose` (or `docker compose -d`, if you want this to run in the - background) -4. Gnoweb should now be accessible from http://localhost:8888 -5. Set up the [test1 key](https://docs.onbloc.xyz/tutorials/start-writing-a-realm#deploying-locally) if you haven't already. -6. Use it to call the realm (visit `localhost:8888/r/demo/chess_XXXX`, XXXX is a - random number, you can check out what was generated for you by calling `docker compose logs deployer | grep 'publishing as'`). - If you visit the help page, gnoweb will generate some commands for you to - call the realm. - -Need more help? Check out a [small video tutorial](https://www.youtube.com/watch?v=-1huuUG2yRc). - -If you're doing local development in the `realm` subdirectory, changes will -synchronise automatically and the realm will be auto-published, however it will -be at a new address. This is published in the `deployer` logs (see above -command). diff --git a/util/devnet/deployer/Dockerfile b/util/devnet/deployer/Dockerfile deleted file mode 100644 index 2f0997e7..00000000 --- a/util/devnet/deployer/Dockerfile +++ /dev/null @@ -1,9 +0,0 @@ -FROM ghcr.io/gnolang/gno/gnochess:latest - -RUN apt-get update && \ - apt-get install -y entr dumb-init - -WORKDIR / -CMD [ "dumb-init", "./deployer.sh" ] - -ADD ./deployer.sh /deployer.sh diff --git a/util/devnet/deployer/deployer.sh b/util/devnet/deployer/deployer.sh deleted file mode 100755 index 209dedaf..00000000 --- a/util/devnet/deployer/deployer.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash -# Auto-deploys realm on any change. - -t1mnemonic="source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast" -export SHELL="/bin/bash" - -if [ ! -f ".deployer.touch" ]; then - printf '\n\n%s\n\n' "$t1mnemonic" | gnokey add --recover --insecure-password-stdin test1 - touch .deployer.touch -fi - -cd realm/ - -sleep 7.5 # get gno node set up - -ls *.gno | entr -ns ' -path=gno.land/r/demo/chess_$RANDOM -echo "publishing as $path" -echo | gnokey maketx addpkg \ - --gas-wanted 50000000 \ - --gas-fee 1ugnot \ - --pkgpath $path \ - --pkgdir . \ - --insecure-password-stdin \ - --remote gnoland:26657 \ - --broadcast test1' diff --git a/util/devnet/docker-compose.yml b/util/devnet/docker-compose.yml deleted file mode 100644 index 95ba4e17..00000000 --- a/util/devnet/docker-compose.yml +++ /dev/null @@ -1,65 +0,0 @@ -version: "3.7" - -services: - web: - build: ../../web - networks: - - gnonode - ports: - - 1313:1313 - restart: on-failure - logging: - driver: "json-file" - options: - max-file: "10" - max-size: "100m" - deployer: - build: ./deployer - networks: - - gnonode - volumes: - - "../../realm:/realm" - restart: on-failure - logging: - driver: "json-file" - options: - max-file: "10" - max-size: "100m" - gnoweb: - image: ghcr.io/gnolang/gno/gnochess:latest - command: ["gnoweb", "-remote", "gnoland:26657", "-bind", "0.0.0.0:8888"] - working_dir: /opt/gno/src/gno.land - networks: - - gnonode - ports: - - 8888:8888 - restart: on-failure - logging: - driver: "json-file" - options: - max-file: "10" - max-size: "100m" - gnoland: - image: ghcr.io/gnolang/gno/gnochess:latest - environment: - - LOG_LEVEL=4 - command: ["gnoland", "start", "-genesis-max-vm-cycles", "100000000"] - volumes: - - "gnonode:/opt/gno/src/testdir" - - "./config.toml:/opt/gno/src/gno.land/testdir/config/config.toml" - working_dir: /opt/gno/src/gno.land - networks: - - gnonode - ports: - - 26657:26657 - restart: on-failure - logging: - driver: "json-file" - options: - max-file: "10" - max-size: "100m" - -networks: - gnonode: {} -volumes: - gnonode: {} diff --git a/util/gnolanddev/Dockerfile b/util/gnolanddev/Dockerfile new file mode 100644 index 00000000..c609d6ac --- /dev/null +++ b/util/gnolanddev/Dockerfile @@ -0,0 +1,25 @@ +FROM ghcr.io/gnolang/gno:latest + +# entr: hot reloading +# dumb-init: signal handling, pid 1 +# rsync: used by run.sh to intelligently copy files +# git, golang: used for applying patches and re-build gno binaries following that +RUN apt-get update && \ + apt-get install -y entr dumb-init rsync git golang + +# symlinked by run.sh +ENV GNOROOT="/opt/gnoroot" + +# XXX: apply patch from PR #1048. +WORKDIR /opt/gno/src +ADD ./pull-1048-assertorigincall.diff . +RUN git apply ./pull-1048-assertorigincall.diff && \ + go build -o /opt/gno/bin/gnoland ./gno.land/cmd/gnoland && \ + go build -o /opt/gno/bin/gno ./gnovm/cmd/gno + +# XXX: add strconv float functions (needed for FormatFloat) +ADD ./strconv ./gnovm/stdlibs/strconv + +WORKDIR /opt/gnoroot +CMD [ "dumb-init", "sh", "-c", "while true; do find /mnt -name '*.gno' | entr -drn /run.sh; done" ] +ADD ./run.sh /run.sh diff --git a/util/devnet/config.toml b/util/gnolanddev/config.toml similarity index 99% rename from util/devnet/config.toml rename to util/gnolanddev/config.toml index 171b111d..f189fad9 100644 --- a/util/devnet/config.toml +++ b/util/gnolanddev/config.toml @@ -5,7 +5,7 @@ # TCP or UNIX socket address of the ABCI application, # or the name of an ABCI application compiled in with the Tendermint binary -proxy_app = "tcp://127.0.0.1:26658" +proxy_app = "tcp://0.0.0.0:26658" # A custom human readable name for this node moniker = "45-79-178-97" diff --git a/util/gnolanddev/pull-1048-assertorigincall.diff b/util/gnolanddev/pull-1048-assertorigincall.diff new file mode 100644 index 00000000..4a87e20f --- /dev/null +++ b/util/gnolanddev/pull-1048-assertorigincall.diff @@ -0,0 +1,1964 @@ +diff --git a/examples/gno.land/r/demo/boards/z_0_a_filetest.gno b/examples/gno.land/r/demo/boards/z_0_a_filetest.gno +index 872d01dd79..ae1724dd86 100644 +--- a/examples/gno.land/r/demo/boards/z_0_a_filetest.gno ++++ b/examples/gno.land/r/demo/boards/z_0_a_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/boards_test +-package boards_test ++package main + + import ( + "gno.land/r/demo/boards" +diff --git a/examples/gno.land/r/demo/boards/z_0_b_filetest.gno b/examples/gno.land/r/demo/boards/z_0_b_filetest.gno +index 9ada8abd0c..70f040eb7b 100644 +--- a/examples/gno.land/r/demo/boards/z_0_b_filetest.gno ++++ b/examples/gno.land/r/demo/boards/z_0_b_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/boards_test +-package boards_test ++package main + + // SEND: 199000000ugnot + +diff --git a/examples/gno.land/r/demo/boards/z_0_c_filetest.gno b/examples/gno.land/r/demo/boards/z_0_c_filetest.gno +index 36b7bcfda0..216e4e4397 100644 +--- a/examples/gno.land/r/demo/boards/z_0_c_filetest.gno ++++ b/examples/gno.land/r/demo/boards/z_0_c_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/boards_test +-package boards_test ++package main + + // SEND: 200000000ugnot + +diff --git a/examples/gno.land/r/demo/boards/z_0_d_filetest.gno b/examples/gno.land/r/demo/boards/z_0_d_filetest.gno +index 2e9e3f1436..9539a9769a 100644 +--- a/examples/gno.land/r/demo/boards/z_0_d_filetest.gno ++++ b/examples/gno.land/r/demo/boards/z_0_d_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/boards_test +-package boards_test ++package main + + // SEND: 200000000ugnot + +diff --git a/examples/gno.land/r/demo/boards/z_0_e_filetest.gno b/examples/gno.land/r/demo/boards/z_0_e_filetest.gno +index a06713fcbe..3411891f46 100644 +--- a/examples/gno.land/r/demo/boards/z_0_e_filetest.gno ++++ b/examples/gno.land/r/demo/boards/z_0_e_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/boards_test +-package boards_test ++package main + + // SEND: 200000000ugnot + +diff --git a/examples/gno.land/r/demo/boards/z_0_filetest.gno b/examples/gno.land/r/demo/boards/z_0_filetest.gno +index 5c3fc7b204..801231b67e 100644 +--- a/examples/gno.land/r/demo/boards/z_0_filetest.gno ++++ b/examples/gno.land/r/demo/boards/z_0_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/boards_test +-package boards_test ++package main + + // SEND: 200000000ugnot + +diff --git a/examples/gno.land/r/demo/boards/z_10_a_filetest.gno b/examples/gno.land/r/demo/boards/z_10_a_filetest.gno +index 8ec2e45421..02abd7dc14 100644 +--- a/examples/gno.land/r/demo/boards/z_10_a_filetest.gno ++++ b/examples/gno.land/r/demo/boards/z_10_a_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/boards_test +-package boards_test ++package main + + // SEND: 200000000ugnot + +diff --git a/examples/gno.land/r/demo/boards/z_10_b_filetest.gno b/examples/gno.land/r/demo/boards/z_10_b_filetest.gno +index 0981d85a57..45a06ccc04 100644 +--- a/examples/gno.land/r/demo/boards/z_10_b_filetest.gno ++++ b/examples/gno.land/r/demo/boards/z_10_b_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/boards_test +-package boards_test ++package main + + // SEND: 2000000000ugnot + +diff --git a/examples/gno.land/r/demo/boards/z_10_c_filetest.gno b/examples/gno.land/r/demo/boards/z_10_c_filetest.gno +index f161c8cede..7f2a180b01 100644 +--- a/examples/gno.land/r/demo/boards/z_10_c_filetest.gno ++++ b/examples/gno.land/r/demo/boards/z_10_c_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/boards_test +-package boards_test ++package main + + // SEND: 200000000ugnot + +diff --git a/examples/gno.land/r/demo/boards/z_10_filetest.gno b/examples/gno.land/r/demo/boards/z_10_filetest.gno +index 7a24efe09c..6f9264d8db 100644 +--- a/examples/gno.land/r/demo/boards/z_10_filetest.gno ++++ b/examples/gno.land/r/demo/boards/z_10_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/boards_test +-package boards_test ++package main + + // SEND: 200000000ugnot + +diff --git a/examples/gno.land/r/demo/boards/z_11_a_filetest.gno b/examples/gno.land/r/demo/boards/z_11_a_filetest.gno +index fd62a884ef..65edb0ddee 100644 +--- a/examples/gno.land/r/demo/boards/z_11_a_filetest.gno ++++ b/examples/gno.land/r/demo/boards/z_11_a_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/boards_test +-package boards_test ++package main + + // SEND: 2000000000ugnot + +diff --git a/examples/gno.land/r/demo/boards/z_11_b_filetest.gno b/examples/gno.land/r/demo/boards/z_11_b_filetest.gno +index 63907146f8..f1547e085d 100644 +--- a/examples/gno.land/r/demo/boards/z_11_b_filetest.gno ++++ b/examples/gno.land/r/demo/boards/z_11_b_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/boards_test +-package boards_test ++package main + + // SEND: 2000000000ugnot + +diff --git a/examples/gno.land/r/demo/boards/z_11_c_filetest.gno b/examples/gno.land/r/demo/boards/z_11_c_filetest.gno +index ba40fa3902..9bec2d5844 100644 +--- a/examples/gno.land/r/demo/boards/z_11_c_filetest.gno ++++ b/examples/gno.land/r/demo/boards/z_11_c_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/boards_test +-package boards_test ++package main + + // SEND: 2000000000ugnot + +diff --git a/examples/gno.land/r/demo/boards/z_11_d_filetest.gno b/examples/gno.land/r/demo/boards/z_11_d_filetest.gno +index a519d4f6a9..7c4abfa36c 100644 +--- a/examples/gno.land/r/demo/boards/z_11_d_filetest.gno ++++ b/examples/gno.land/r/demo/boards/z_11_d_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/boards_test +-package boards_test ++package main + + // SEND: 2000000000ugnot + +diff --git a/examples/gno.land/r/demo/boards/z_11_filetest.gno b/examples/gno.land/r/demo/boards/z_11_filetest.gno +index 2d96d46dc9..d38b0223cd 100644 +--- a/examples/gno.land/r/demo/boards/z_11_filetest.gno ++++ b/examples/gno.land/r/demo/boards/z_11_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/boards_test +-package boards_test ++package main + + // SEND: 2000000000ugnot + +diff --git a/examples/gno.land/r/demo/boards/z_1_filetest.gno b/examples/gno.land/r/demo/boards/z_1_filetest.gno +index b5c7bb863e..13bea83ae4 100644 +--- a/examples/gno.land/r/demo/boards/z_1_filetest.gno ++++ b/examples/gno.land/r/demo/boards/z_1_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/boards_test +-package boards_test ++package main + + // SEND: 200000000ugnot + +diff --git a/examples/gno.land/r/demo/boards/z_2_filetest.gno b/examples/gno.land/r/demo/boards/z_2_filetest.gno +index 1e0b55a395..547757ef0a 100644 +--- a/examples/gno.land/r/demo/boards/z_2_filetest.gno ++++ b/examples/gno.land/r/demo/boards/z_2_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/boards_test +-package boards_test ++package main + + // SEND: 200000000ugnot + +diff --git a/examples/gno.land/r/demo/boards/z_3_filetest.gno b/examples/gno.land/r/demo/boards/z_3_filetest.gno +index f4160e1612..757f9430c6 100644 +--- a/examples/gno.land/r/demo/boards/z_3_filetest.gno ++++ b/examples/gno.land/r/demo/boards/z_3_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/boards_test +-package boards_test ++package main + + // SEND: 200000000ugnot + +diff --git a/examples/gno.land/r/demo/boards/z_4_filetest.gno b/examples/gno.land/r/demo/boards/z_4_filetest.gno +index 749566ea5b..68b1955ae3 100644 +--- a/examples/gno.land/r/demo/boards/z_4_filetest.gno ++++ b/examples/gno.land/r/demo/boards/z_4_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/boards_test +-package boards_test ++package main + + // SEND: 200000000ugnot + +@@ -44,929 +43,3 @@ func main() { + // + // > Second reply of the second post + // > \- [@gnouser](/r/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/4) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=4&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=4)] +- +-// Realm: +-// switchrealm["gno.land/r/demo/users"] +-// switchrealm["gno.land/r/demo/users"] +-// switchrealm["gno.land/r/demo/boards"] +-// u[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:101]={ +-// "Fields": [ +-// { +-// "T": { +-// "@type": "/gno.PrimitiveType", +-// "value": "16" +-// }, +-// "V": { +-// "@type": "/gno.StringValue", +-// "value": "0000000003" +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.PointerType", +-// "Elt": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/r/demo/boards.Post" +-// } +-// }, +-// "V": { +-// "@type": "/gno.PointerValue", +-// "Base": null, +-// "Index": "0", +-// "TV": { +-// "T": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/r/demo/boards.Post" +-// }, +-// "V": { +-// "@type": "/gno.RefValue", +-// "Escaped": true, +-// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:102" +-// } +-// } +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.PrimitiveType", +-// "value": "64" +-// } +-// }, +-// { +-// "N": "AQAAAAAAAAA=", +-// "T": { +-// "@type": "/gno.PrimitiveType", +-// "value": "32" +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.PointerType", +-// "Elt": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/p/demo/avl.Node" +-// } +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.PointerType", +-// "Elt": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/p/demo/avl.Node" +-// } +-// } +-// } +-// ], +-// "ObjectInfo": { +-// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:101", +-// "ModTime": "109", +-// "OwnerID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:109", +-// "RefCount": "1" +-// } +-// } +-// c[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:110]={ +-// "Fields": [ +-// { +-// "T": { +-// "@type": "/gno.PrimitiveType", +-// "value": "16" +-// }, +-// "V": { +-// "@type": "/gno.StringValue", +-// "value": "0000000004" +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.PointerType", +-// "Elt": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/r/demo/boards.Post" +-// } +-// }, +-// "V": { +-// "@type": "/gno.PointerValue", +-// "Base": null, +-// "Index": "0", +-// "TV": { +-// "T": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/r/demo/boards.Post" +-// }, +-// "V": { +-// "@type": "/gno.RefValue", +-// "Escaped": true, +-// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:111" +-// } +-// } +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.PrimitiveType", +-// "value": "64" +-// } +-// }, +-// { +-// "N": "AQAAAAAAAAA=", +-// "T": { +-// "@type": "/gno.PrimitiveType", +-// "value": "32" +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.PointerType", +-// "Elt": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/p/demo/avl.Node" +-// } +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.PointerType", +-// "Elt": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/p/demo/avl.Node" +-// } +-// } +-// } +-// ], +-// "ObjectInfo": { +-// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:110", +-// "ModTime": "0", +-// "OwnerID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:109", +-// "RefCount": "1" +-// } +-// } +-// c[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:109]={ +-// "Fields": [ +-// { +-// "T": { +-// "@type": "/gno.PrimitiveType", +-// "value": "16" +-// }, +-// "V": { +-// "@type": "/gno.StringValue", +-// "value": "0000000004" +-// } +-// }, +-// {}, +-// { +-// "N": "AQAAAAAAAAA=", +-// "T": { +-// "@type": "/gno.PrimitiveType", +-// "value": "64" +-// } +-// }, +-// { +-// "N": "AgAAAAAAAAA=", +-// "T": { +-// "@type": "/gno.PrimitiveType", +-// "value": "32" +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.PointerType", +-// "Elt": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/p/demo/avl.Node" +-// } +-// }, +-// "V": { +-// "@type": "/gno.PointerValue", +-// "Base": null, +-// "Index": "0", +-// "TV": { +-// "T": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/p/demo/avl.Node" +-// }, +-// "V": { +-// "@type": "/gno.RefValue", +-// "Hash": "b58581159917d8d7ad0992009d7184fc8ca00fcc", +-// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:101" +-// } +-// } +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.PointerType", +-// "Elt": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/p/demo/avl.Node" +-// } +-// }, +-// "V": { +-// "@type": "/gno.PointerValue", +-// "Base": null, +-// "Index": "0", +-// "TV": { +-// "T": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/p/demo/avl.Node" +-// }, +-// "V": { +-// "@type": "/gno.RefValue", +-// "Hash": "fb593e86d35aaf607e0d21e6bd4f84519c44585f", +-// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:110" +-// } +-// } +-// } +-// } +-// ], +-// "ObjectInfo": { +-// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:109", +-// "ModTime": "0", +-// "OwnerID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:96", +-// "RefCount": "1" +-// } +-// } +-// c[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:112]={ +-// "Fields": [ +-// { +-// "T": { +-// "@type": "/gno.PointerType", +-// "Elt": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/p/demo/avl.Node" +-// } +-// } +-// } +-// ], +-// "ObjectInfo": { +-// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:112", +-// "ModTime": "0", +-// "OwnerID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:111", +-// "RefCount": "1" +-// } +-// } +-// c[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:113]={ +-// "Fields": [ +-// { +-// "T": { +-// "@type": "/gno.PointerType", +-// "Elt": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/p/demo/avl.Node" +-// } +-// } +-// } +-// ], +-// "ObjectInfo": { +-// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:113", +-// "ModTime": "0", +-// "OwnerID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:111", +-// "RefCount": "1" +-// } +-// } +-// c[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:114]={ +-// "Fields": [ +-// { +-// "T": { +-// "@type": "/gno.PointerType", +-// "Elt": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/p/demo/avl.Node" +-// } +-// } +-// } +-// ], +-// "ObjectInfo": { +-// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:114", +-// "ModTime": "0", +-// "OwnerID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:111", +-// "RefCount": "1" +-// } +-// } +-// c[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:115]={ +-// "Fields": [ +-// { +-// "N": "AAAAgJSeXbo=", +-// "T": { +-// "@type": "/gno.PrimitiveType", +-// "value": "65536" +-// } +-// }, +-// { +-// "N": "AbSNdvQQIhE=", +-// "T": { +-// "@type": "/gno.PrimitiveType", +-// "value": "1024" +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.PointerType", +-// "Elt": { +-// "@type": "/gno.RefType", +-// "ID": "time.Location" +-// } +-// }, +-// "V": { +-// "@type": "/gno.PointerValue", +-// "Base": { +-// "@type": "/gno.RefValue", +-// "Escaped": true, +-// "ObjectID": "336074805fc853987abe6f7fe3ad97a6a6f3077a:2" +-// }, +-// "Index": "188", +-// "TV": null +-// } +-// } +-// ], +-// "ObjectInfo": { +-// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:115", +-// "ModTime": "0", +-// "OwnerID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:111", +-// "RefCount": "1" +-// } +-// } +-// c[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:116]={ +-// "Fields": [ +-// { +-// "T": { +-// "@type": "/gno.PrimitiveType", +-// "value": "65536" +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.PrimitiveType", +-// "value": "1024" +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.PointerType", +-// "Elt": { +-// "@type": "/gno.RefType", +-// "ID": "time.Location" +-// } +-// } +-// } +-// ], +-// "ObjectInfo": { +-// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:116", +-// "ModTime": "0", +-// "OwnerID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:111", +-// "RefCount": "1" +-// } +-// } +-// c[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:111]={ +-// "Fields": [ +-// { +-// "T": { +-// "@type": "/gno.PointerType", +-// "Elt": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/r/demo/boards.Board" +-// } +-// }, +-// "V": { +-// "@type": "/gno.PointerValue", +-// "Base": null, +-// "Index": "0", +-// "TV": { +-// "T": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/r/demo/boards.Board" +-// }, +-// "V": { +-// "@type": "/gno.RefValue", +-// "Escaped": true, +-// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:81" +-// } +-// } +-// } +-// }, +-// { +-// "N": "BAAAAAAAAAA=", +-// "T": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/r/demo/boards.PostID" +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.RefType", +-// "ID": "std.Address" +-// }, +-// "V": { +-// "@type": "/gno.StringValue", +-// "value": "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.PrimitiveType", +-// "value": "16" +-// }, +-// "V": { +-// "@type": "/gno.StringValue", +-// "value": "" +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.PrimitiveType", +-// "value": "16" +-// }, +-// "V": { +-// "@type": "/gno.StringValue", +-// "value": "Second reply of the second post" +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/p/demo/avl.Tree" +-// }, +-// "V": { +-// "@type": "/gno.RefValue", +-// "Hash": "130542396d7549d1d516a3ef4a63bb44ef3da06f", +-// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:112" +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/p/demo/avl.Tree" +-// }, +-// "V": { +-// "@type": "/gno.RefValue", +-// "Hash": "80acd8746478317194b8546170335c796a4dfb3f", +-// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:113" +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/p/demo/avl.Tree" +-// }, +-// "V": { +-// "@type": "/gno.RefValue", +-// "Hash": "c1a8f769f3b9d52dd38ac4759116edaca287636f", +-// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:114" +-// } +-// }, +-// { +-// "N": "AgAAAAAAAAA=", +-// "T": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/r/demo/boards.PostID" +-// } +-// }, +-// { +-// "N": "AgAAAAAAAAA=", +-// "T": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/r/demo/boards.PostID" +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/r/demo/boards.BoardID" +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.RefType", +-// "ID": "time.Time" +-// }, +-// "V": { +-// "@type": "/gno.RefValue", +-// "Hash": "8164abed5231309c88497013f7da72a1b5d427b0", +-// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:115" +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.RefType", +-// "ID": "time.Time" +-// }, +-// "V": { +-// "@type": "/gno.RefValue", +-// "Hash": "c3a60b602b564d07677a212372f4ac1cae4270fd", +-// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:116" +-// } +-// } +-// ], +-// "ObjectInfo": { +-// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:111", +-// "IsEscaped": true, +-// "ModTime": "0", +-// "RefCount": "2" +-// } +-// } +-// u[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:108]={ +-// "Fields": [ +-// { +-// "T": { +-// "@type": "/gno.PrimitiveType", +-// "value": "16" +-// }, +-// "V": { +-// "@type": "/gno.StringValue", +-// "value": "0000000003" +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.PointerType", +-// "Elt": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/r/demo/boards.Post" +-// } +-// }, +-// "V": { +-// "@type": "/gno.PointerValue", +-// "Base": null, +-// "Index": "0", +-// "TV": { +-// "T": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/r/demo/boards.Post" +-// }, +-// "V": { +-// "@type": "/gno.RefValue", +-// "Escaped": true, +-// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:102" +-// } +-// } +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.PrimitiveType", +-// "value": "64" +-// } +-// }, +-// { +-// "N": "AQAAAAAAAAA=", +-// "T": { +-// "@type": "/gno.PrimitiveType", +-// "value": "32" +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.PointerType", +-// "Elt": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/p/demo/avl.Node" +-// } +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.PointerType", +-// "Elt": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/p/demo/avl.Node" +-// } +-// } +-// } +-// ], +-// "ObjectInfo": { +-// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:108", +-// "ModTime": "117", +-// "OwnerID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:117", +-// "RefCount": "1" +-// } +-// } +-// c[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:118]={ +-// "Fields": [ +-// { +-// "T": { +-// "@type": "/gno.PrimitiveType", +-// "value": "16" +-// }, +-// "V": { +-// "@type": "/gno.StringValue", +-// "value": "0000000004" +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.PointerType", +-// "Elt": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/r/demo/boards.Post" +-// } +-// }, +-// "V": { +-// "@type": "/gno.PointerValue", +-// "Base": null, +-// "Index": "0", +-// "TV": { +-// "T": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/r/demo/boards.Post" +-// }, +-// "V": { +-// "@type": "/gno.RefValue", +-// "Escaped": true, +-// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:111" +-// } +-// } +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.PrimitiveType", +-// "value": "64" +-// } +-// }, +-// { +-// "N": "AQAAAAAAAAA=", +-// "T": { +-// "@type": "/gno.PrimitiveType", +-// "value": "32" +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.PointerType", +-// "Elt": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/p/demo/avl.Node" +-// } +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.PointerType", +-// "Elt": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/p/demo/avl.Node" +-// } +-// } +-// } +-// ], +-// "ObjectInfo": { +-// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:118", +-// "ModTime": "0", +-// "OwnerID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:117", +-// "RefCount": "1" +-// } +-// } +-// c[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:117]={ +-// "Fields": [ +-// { +-// "T": { +-// "@type": "/gno.PrimitiveType", +-// "value": "16" +-// }, +-// "V": { +-// "@type": "/gno.StringValue", +-// "value": "0000000004" +-// } +-// }, +-// {}, +-// { +-// "N": "AQAAAAAAAAA=", +-// "T": { +-// "@type": "/gno.PrimitiveType", +-// "value": "64" +-// } +-// }, +-// { +-// "N": "AgAAAAAAAAA=", +-// "T": { +-// "@type": "/gno.PrimitiveType", +-// "value": "32" +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.PointerType", +-// "Elt": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/p/demo/avl.Node" +-// } +-// }, +-// "V": { +-// "@type": "/gno.PointerValue", +-// "Base": null, +-// "Index": "0", +-// "TV": { +-// "T": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/p/demo/avl.Node" +-// }, +-// "V": { +-// "@type": "/gno.RefValue", +-// "Hash": "6a86bc7763703c8f2b9d286368921159d6db121c", +-// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:108" +-// } +-// } +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.PointerType", +-// "Elt": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/p/demo/avl.Node" +-// } +-// }, +-// "V": { +-// "@type": "/gno.PointerValue", +-// "Base": null, +-// "Index": "0", +-// "TV": { +-// "T": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/p/demo/avl.Node" +-// }, +-// "V": { +-// "@type": "/gno.RefValue", +-// "Hash": "52faa8a2dfefd4b6b6249eff2f9c123ad455e81d", +-// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:118" +-// } +-// } +-// } +-// } +-// ], +-// "ObjectInfo": { +-// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:117", +-// "ModTime": "0", +-// "OwnerID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:97", +-// "RefCount": "1" +-// } +-// } +-// u[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:81]={ +-// "Fields": [ +-// { +-// "N": "AQAAAAAAAAA=", +-// "T": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/r/demo/boards.BoardID" +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.PrimitiveType", +-// "value": "16" +-// }, +-// "V": { +-// "@type": "/gno.StringValue", +-// "value": "/r/demo/boards:test_board" +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.PrimitiveType", +-// "value": "16" +-// }, +-// "V": { +-// "@type": "/gno.StringValue", +-// "value": "test_board" +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.RefType", +-// "ID": "std.Address" +-// }, +-// "V": { +-// "@type": "/gno.StringValue", +-// "value": "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/p/demo/avl.Tree" +-// }, +-// "V": { +-// "@type": "/gno.RefValue", +-// "Hash": "5b4b593f1d4b37cb99166247ea28174f91087fdd", +-// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:82" +-// } +-// }, +-// { +-// "N": "BAAAAAAAAAA=", +-// "T": { +-// "@type": "/gno.PrimitiveType", +-// "value": "65536" +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.RefType", +-// "ID": "time.Time" +-// }, +-// "V": { +-// "@type": "/gno.RefValue", +-// "Hash": "7e9fd9bb5e90a06c7751585cd80f23aedddde25b", +-// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:83" +-// } +-// }, +-// { +-// "T": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/p/demo/avl.Tree" +-// }, +-// "V": { +-// "@type": "/gno.RefValue", +-// "Hash": "edb1857302fa916c562cd077cdf2a3626e29ae2b", +-// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:84" +-// } +-// } +-// ], +-// "ObjectInfo": { +-// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:81", +-// "IsEscaped": true, +-// "ModTime": "108", +-// "RefCount": "6" +-// } +-// } +-// u[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:96]={ +-// "Fields": [ +-// { +-// "T": { +-// "@type": "/gno.PointerType", +-// "Elt": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/p/demo/avl.Node" +-// } +-// }, +-// "V": { +-// "@type": "/gno.PointerValue", +-// "Base": null, +-// "Index": "0", +-// "TV": { +-// "T": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/p/demo/avl.Node" +-// }, +-// "V": { +-// "@type": "/gno.RefValue", +-// "Hash": "609e7f519c65f94503427a14f973b4b83989cdc8", +-// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:109" +-// } +-// } +-// } +-// } +-// ], +-// "ObjectInfo": { +-// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:96", +-// "ModTime": "108", +-// "OwnerID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:95", +-// "RefCount": "1" +-// } +-// } +-// u[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:97]={ +-// "Fields": [ +-// { +-// "T": { +-// "@type": "/gno.PointerType", +-// "Elt": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/p/demo/avl.Node" +-// } +-// }, +-// "V": { +-// "@type": "/gno.PointerValue", +-// "Base": null, +-// "Index": "0", +-// "TV": { +-// "T": { +-// "@type": "/gno.RefType", +-// "ID": "gno.land/p/demo/avl.Node" +-// }, +-// "V": { +-// "@type": "/gno.RefValue", +-// "Hash": "6760340f5b40e05221dc530940683b0b9a422503", +-// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:117" +-// } +-// } +-// } +-// } +-// ], +-// "ObjectInfo": { +-// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:97", +-// "ModTime": "108", +-// "OwnerID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:95", +-// "RefCount": "1" +-// } +-// } +-// switchrealm["gno.land/r/demo/boards"] +-// switchrealm["gno.land/r/demo/users"] +-// switchrealm["gno.land/r/demo/users"] +-// switchrealm["gno.land/r/demo/users"] +-// switchrealm["gno.land/r/demo/users"] +-// switchrealm["gno.land/r/demo/users"] +-// switchrealm["gno.land/r/demo/users"] +-// switchrealm["gno.land/r/demo/users"] +-// switchrealm["gno.land/r/demo/users"] +-// switchrealm["gno.land/r/demo/users"] +-// switchrealm["gno.land/r/demo/boards"] +-// switchrealm["gno.land/r/boards_test"] +diff --git a/examples/gno.land/r/demo/boards/z_5_filetest.gno b/examples/gno.land/r/demo/boards/z_5_filetest.gno +index 421d944078..d9ebf69e0d 100644 +--- a/examples/gno.land/r/demo/boards/z_5_filetest.gno ++++ b/examples/gno.land/r/demo/boards/z_5_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/boards_test +-package boards_test ++package main + + // SEND: 200000000ugnot + +diff --git a/examples/gno.land/r/demo/boards/z_6_filetest.gno b/examples/gno.land/r/demo/boards/z_6_filetest.gno +index 2a392808d3..6647848894 100644 +--- a/examples/gno.land/r/demo/boards/z_6_filetest.gno ++++ b/examples/gno.land/r/demo/boards/z_6_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/boards_test +-package boards_test ++package main + + // SEND: 200000000ugnot + +diff --git a/examples/gno.land/r/demo/boards/z_7_filetest.gno b/examples/gno.land/r/demo/boards/z_7_filetest.gno +index 1294f72c1b..bb46372ec7 100644 +--- a/examples/gno.land/r/demo/boards/z_7_filetest.gno ++++ b/examples/gno.land/r/demo/boards/z_7_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/boards_test +-package boards_test ++package main + + // SEND: 2000000000ugnot + +diff --git a/examples/gno.land/r/demo/boards/z_8_filetest.gno b/examples/gno.land/r/demo/boards/z_8_filetest.gno +index 5ba0b34ad3..c4e6c33643 100644 +--- a/examples/gno.land/r/demo/boards/z_8_filetest.gno ++++ b/examples/gno.land/r/demo/boards/z_8_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/boards_test +-package boards_test ++package main + + // SEND: 2000000000ugnot + +diff --git a/examples/gno.land/r/demo/boards/z_9_a_filetest.gno b/examples/gno.land/r/demo/boards/z_9_a_filetest.gno +index 9ba9786c51..351235fba3 100644 +--- a/examples/gno.land/r/demo/boards/z_9_a_filetest.gno ++++ b/examples/gno.land/r/demo/boards/z_9_a_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/boards_test +-package boards_test ++package main + + // SEND: 200000000ugnot + +diff --git a/examples/gno.land/r/demo/boards/z_9_b_filetest.gno b/examples/gno.land/r/demo/boards/z_9_b_filetest.gno +index 4d53f60f10..7715456564 100644 +--- a/examples/gno.land/r/demo/boards/z_9_b_filetest.gno ++++ b/examples/gno.land/r/demo/boards/z_9_b_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/boards_test +-package boards_test ++package main + + // SEND: 200000000ugnot + +diff --git a/examples/gno.land/r/demo/boards/z_9_filetest.gno b/examples/gno.land/r/demo/boards/z_9_filetest.gno +index 66f8950732..7461a3b67c 100644 +--- a/examples/gno.land/r/demo/boards/z_9_filetest.gno ++++ b/examples/gno.land/r/demo/boards/z_9_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/boards_test +-package boards_test ++package main + + // SEND: 200000000ugnot + +diff --git a/examples/gno.land/r/demo/groups/z_0_a_filetest.gno b/examples/gno.land/r/demo/groups/z_0_a_filetest.gno +index 41d515b9d0..95c5c2d0e6 100644 +--- a/examples/gno.land/r/demo/groups/z_0_a_filetest.gno ++++ b/examples/gno.land/r/demo/groups/z_0_a_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/groups_test +-package groups_test ++package main + + import ( + "gno.land/r/demo/groups" +diff --git a/examples/gno.land/r/demo/groups/z_0_b_filetest.gno b/examples/gno.land/r/demo/groups/z_0_b_filetest.gno +index ca74c59913..047a5915bb 100644 +--- a/examples/gno.land/r/demo/groups/z_0_b_filetest.gno ++++ b/examples/gno.land/r/demo/groups/z_0_b_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/groups_test +-package groups_test ++package main + + import ( + "gno.land/r/demo/groups" +diff --git a/examples/gno.land/r/demo/groups/z_0_c_filetest.gno b/examples/gno.land/r/demo/groups/z_0_c_filetest.gno +index 10a4771c52..92fc412374 100644 +--- a/examples/gno.land/r/demo/groups/z_0_c_filetest.gno ++++ b/examples/gno.land/r/demo/groups/z_0_c_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/groups_test +-package groups_test ++package main + + // SEND: 200000000ugnot + +diff --git a/examples/gno.land/r/demo/groups/z_1_a_filetest.gno b/examples/gno.land/r/demo/groups/z_1_a_filetest.gno +index 460fb79afb..8a957f1de1 100644 +--- a/examples/gno.land/r/demo/groups/z_1_a_filetest.gno ++++ b/examples/gno.land/r/demo/groups/z_1_a_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/groups_test +-package groups_test ++package main + + // SEND: 200000000ugnot + +diff --git a/examples/gno.land/r/demo/groups/z_1_b_filetest.gno b/examples/gno.land/r/demo/groups/z_1_b_filetest.gno +index 3271e74e28..99ed8e39b1 100644 +--- a/examples/gno.land/r/demo/groups/z_1_b_filetest.gno ++++ b/examples/gno.land/r/demo/groups/z_1_b_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/groups_test +-package groups_test ++package main + + // SEND: 200000000ugnot + +diff --git a/examples/gno.land/r/demo/groups/z_1_c_filetest.gno b/examples/gno.land/r/demo/groups/z_1_c_filetest.gno +index 93cd3b39d5..e2988c7d9d 100644 +--- a/examples/gno.land/r/demo/groups/z_1_c_filetest.gno ++++ b/examples/gno.land/r/demo/groups/z_1_c_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/groups_test +-package groups_test ++package main + + // SEND: 200000000ugnot + +diff --git a/examples/gno.land/r/demo/groups/z_2_a_filetest.gno b/examples/gno.land/r/demo/groups/z_2_a_filetest.gno +index f4a96905fc..7136ae0433 100644 +--- a/examples/gno.land/r/demo/groups/z_2_a_filetest.gno ++++ b/examples/gno.land/r/demo/groups/z_2_a_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/groups_test +-package groups_test ++package main + + // SEND: 200000000ugnot + +diff --git a/examples/gno.land/r/demo/groups/z_2_b_filetest.gno b/examples/gno.land/r/demo/groups/z_2_b_filetest.gno +index bf10939c66..5614c8039b 100644 +--- a/examples/gno.land/r/demo/groups/z_2_b_filetest.gno ++++ b/examples/gno.land/r/demo/groups/z_2_b_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/groups_test +-package groups_test ++package main + + // SEND: 200000000ugnot + +diff --git a/examples/gno.land/r/demo/groups/z_2_d_filetest.gno b/examples/gno.land/r/demo/groups/z_2_d_filetest.gno +index 95f22f4ec4..c45e6c3b2a 100644 +--- a/examples/gno.land/r/demo/groups/z_2_d_filetest.gno ++++ b/examples/gno.land/r/demo/groups/z_2_d_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/groups_test +-package groups_test ++package main + + // SEND: 200000000ugnot + +diff --git a/examples/gno.land/r/demo/groups/z_2_e_filetest.gno b/examples/gno.land/r/demo/groups/z_2_e_filetest.gno +index 270ddb8aa3..6ebc4d8bbe 100644 +--- a/examples/gno.land/r/demo/groups/z_2_e_filetest.gno ++++ b/examples/gno.land/r/demo/groups/z_2_e_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/groups_test +-package groups_test ++package main + + // SEND: 200000000ugnot + +diff --git a/examples/gno.land/r/demo/groups/z_2_f_filetest.gno b/examples/gno.land/r/demo/groups/z_2_f_filetest.gno +index 4ec0ec211f..9c51e31edf 100644 +--- a/examples/gno.land/r/demo/groups/z_2_f_filetest.gno ++++ b/examples/gno.land/r/demo/groups/z_2_f_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/groups_test +-package groups_test ++package main + + // SEND: 200000000ugnot + +diff --git a/examples/gno.land/r/demo/groups/z_2_g_filetest.gno b/examples/gno.land/r/demo/groups/z_2_g_filetest.gno +index 8f98cfeb2d..cd5ebf62c8 100644 +--- a/examples/gno.land/r/demo/groups/z_2_g_filetest.gno ++++ b/examples/gno.land/r/demo/groups/z_2_g_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/groups_test +-package groups_test ++package main + + // SEND: 200000000ugnot + +diff --git a/examples/gno.land/r/demo/tests/subtests/subtests.gno b/examples/gno.land/r/demo/tests/subtests/subtests.gno +index e8796a7308..5cc4d1bea1 100644 +--- a/examples/gno.land/r/demo/tests/subtests/subtests.gno ++++ b/examples/gno.land/r/demo/tests/subtests/subtests.gno +@@ -15,3 +15,11 @@ func GetPrevRealm() std.Realm { + func Exec(fn func()) { + fn() + } ++ ++func AssertOriginCall() { ++ std.AssertOriginCall() ++} ++ ++func IsOriginCall() bool { ++ return std.IsOriginCall() ++} +diff --git a/examples/gno.land/r/demo/tests/tests.gno b/examples/gno.land/r/demo/tests/tests.gno +index fb49b2273a..67ae4bc917 100644 +--- a/examples/gno.land/r/demo/tests/tests.gno ++++ b/examples/gno.land/r/demo/tests/tests.gno +@@ -28,6 +28,14 @@ func IsOriginCall() bool { + return std.IsOriginCall() + } + ++func RSubtestsAssertOriginCall() { ++ rsubtests.AssertOriginCall() ++} ++ ++func RSubtestsIsOriginCall() bool { ++ return rsubtests.IsOriginCall() ++} ++ + //---------------------------------------- + // Test structure to ensure cross-realm modification is prevented. + +diff --git a/examples/gno.land/r/demo/tests/tests_test.gno b/examples/gno.land/r/demo/tests/tests_test.gno +index 3dcbeecf18..3c92613d3d 100644 +--- a/examples/gno.land/r/demo/tests/tests_test.gno ++++ b/examples/gno.land/r/demo/tests/tests_test.gno +@@ -22,14 +22,10 @@ func TestAssertOriginCall(t *testing.T) { + t.Errorf("expected panic with '%v', got '%v'", expectedReason, r) + } + }() +- func() { +- // if called inside a function literal, this is no longer an origin call +- // because there's one additional frame (the function literal). +- if IsOriginCall() { +- t.Errorf("expected IsOriginCall=false but got true") +- } +- AssertOriginCall() +- }() ++ if RSubtestsIsOriginCall() { ++ t.Errorf("expected RSubtestsIsOriginCall=false but got true") ++ } ++ RSubtestsAssertOriginCall() + } + + func TestPrevRealm(t *testing.T) { +diff --git a/examples/gno.land/r/demo/tests/z0_filetest.gno b/examples/gno.land/r/demo/tests/z0_filetest.gno +index c4beb8e200..2f5ab9fa05 100644 +--- a/examples/gno.land/r/demo/tests/z0_filetest.gno ++++ b/examples/gno.land/r/demo/tests/z0_filetest.gno +@@ -9,16 +9,12 @@ func main() { + tests.AssertOriginCall() + println("AssertOriginCall doesn't panic when called directly") + +- func() { +- // if called inside a function literal, this is no longer an origin call +- // because there's one additional frame (the function literal). +- println("IsOriginCall:", tests.IsOriginCall()) +- defer func() { +- r := recover() +- println("AssertOriginCall panics if when called inside a function literal:", r) +- }() +- tests.AssertOriginCall() ++ println("IsOriginCall:", tests.RSubtestsIsOriginCall()) ++ defer func() { ++ r := recover() ++ println("AssertOriginCall panics if when called inside a function literal:", r) + }() ++ tests.RSubtestsAssertOriginCall() + } + + // Output: +diff --git a/examples/gno.land/r/demo/users/z_10_filetest.gno b/examples/gno.land/r/demo/users/z_10_filetest.gno +index 0065d907e4..607ced8e2d 100644 +--- a/examples/gno.land/r/demo/users/z_10_filetest.gno ++++ b/examples/gno.land/r/demo/users/z_10_filetest.gno +@@ -1,5 +1,4 @@ +-// PKGPATH: gno.land/r/users_test +-package users_test ++package main + + import ( + "std" +diff --git a/gnovm/stdlibs/frame.go b/gnovm/stdlibs/frame.go +index e428bb1776..a8c50ee6bf 100644 +--- a/gnovm/stdlibs/frame.go ++++ b/gnovm/stdlibs/frame.go +@@ -1,6 +1,9 @@ + package stdlibs + +-import "github.com/gnolang/gno/tm2/pkg/crypto" ++import ( ++ gno "github.com/gnolang/gno/gnovm/pkg/gnolang" ++ "github.com/gnolang/gno/tm2/pkg/crypto" ++) + + type Realm struct { + addr crypto.Bech32Address +@@ -18,3 +21,39 @@ func (r Realm) PkgPath() string { + func (r Realm) IsUser() bool { + return r.pkgPath == "" + } ++ ++// isOriginCall returns true if the std.OrigCaller == std.PrevRealm ++func isOriginCall(m *gno.Machine) bool { ++ return prevRealm(m).addr == m.Context.(ExecContext).OrigCaller ++} ++ ++// prevRealm loops on frames and returns the second realm found in the calling ++// order. If no such realm was found, returns the tx signer (aka OrigCaller). ++func prevRealm(m *gno.Machine) Realm { ++ var lastRealmPath string ++ for i := m.NumFrames() - 1; i > 0; i-- { ++ fr := m.Frames[i] ++ if fr.LastPackage == nil || !fr.LastPackage.IsRealm() { ++ // Ignore non-realm frame ++ continue ++ } ++ realmPath := fr.LastPackage.PkgPath ++ if lastRealmPath == "" { ++ // Record the path of the first encountered realm and continue ++ lastRealmPath = realmPath ++ continue ++ } ++ if lastRealmPath != realmPath { ++ // Second realm detected, return it. ++ return Realm{ ++ addr: fr.LastPackage.GetPkgAddr().Bech32(), ++ pkgPath: realmPath, ++ } ++ } ++ } ++ // No second realm found, return the tx signer. ++ return Realm{ ++ addr: m.Context.(ExecContext).OrigCaller, ++ pkgPath: "", // empty for users ++ } ++} +diff --git a/gnovm/stdlibs/frame_test.go b/gnovm/stdlibs/frame_test.go +new file mode 100644 +index 0000000000..fdcb324cd0 +--- /dev/null ++++ b/gnovm/stdlibs/frame_test.go +@@ -0,0 +1,125 @@ ++package stdlibs ++ ++import ( ++ "testing" ++ ++ "github.com/stretchr/testify/assert" ++ ++ gno "github.com/gnolang/gno/gnovm/pkg/gnolang" ++) ++ ++func TestPrevRealmIsOrigin(t *testing.T) { ++ var ( ++ user = gno.DerivePkgAddr("user1.gno").Bech32() ++ ctx = ExecContext{ ++ OrigCaller: user, ++ } ++ ) ++ tests := []struct { ++ name string ++ machine *gno.Machine ++ expectedRealm Realm ++ expectedIsOriginCall bool ++ }{ ++ { ++ name: "no frames", ++ machine: &gno.Machine{ ++ Context: ctx, ++ Frames: []gno.Frame{}, ++ }, ++ expectedRealm: Realm{ ++ addr: user, ++ pkgPath: "", ++ }, ++ expectedIsOriginCall: true, ++ }, ++ { ++ name: "one frame w/o LastPackage", ++ machine: &gno.Machine{ ++ Context: ctx, ++ Frames: []gno.Frame{ ++ {LastPackage: nil}, ++ }, ++ }, ++ expectedRealm: Realm{ ++ addr: user, ++ pkgPath: "", ++ }, ++ expectedIsOriginCall: true, ++ }, ++ { ++ name: "one non-realm frame", ++ machine: &gno.Machine{ ++ Context: ctx, ++ Frames: []gno.Frame{ ++ {LastPackage: &gno.PackageValue{PkgPath: "gno.land/p/xxx"}}, ++ }, ++ }, ++ expectedRealm: Realm{ ++ addr: user, ++ pkgPath: "", ++ }, ++ expectedIsOriginCall: true, ++ }, ++ { ++ name: "one realm frame", ++ machine: &gno.Machine{ ++ Context: ctx, ++ Frames: []gno.Frame{ ++ {LastPackage: &gno.PackageValue{PkgPath: "gno.land/r/xxx"}}, ++ }, ++ }, ++ expectedRealm: Realm{ ++ addr: user, ++ pkgPath: "", ++ }, ++ expectedIsOriginCall: true, ++ }, ++ { ++ name: "multiple frames with one realm", ++ machine: &gno.Machine{ ++ Context: ctx, ++ Frames: []gno.Frame{ ++ {LastPackage: &gno.PackageValue{PkgPath: "gno.land/p/xxx"}}, ++ {LastPackage: &gno.PackageValue{PkgPath: "gno.land/p/xxx"}}, ++ {LastPackage: &gno.PackageValue{PkgPath: "gno.land/r/xxx"}}, ++ }, ++ }, ++ expectedRealm: Realm{ ++ addr: user, ++ pkgPath: "", ++ }, ++ expectedIsOriginCall: true, ++ }, ++ { ++ name: "multiple frames with multiple realms", ++ machine: &gno.Machine{ ++ Context: ctx, ++ Frames: []gno.Frame{ ++ {LastPackage: &gno.PackageValue{PkgPath: "gno.land/r/zzz"}}, ++ {LastPackage: &gno.PackageValue{PkgPath: "gno.land/r/zzz"}}, ++ {LastPackage: &gno.PackageValue{PkgPath: "gno.land/r/yyy"}}, ++ {LastPackage: &gno.PackageValue{PkgPath: "gno.land/p/yyy"}}, ++ {LastPackage: &gno.PackageValue{PkgPath: "gno.land/p/xxx"}}, ++ {LastPackage: &gno.PackageValue{PkgPath: "gno.land/r/xxx"}}, ++ }, ++ }, ++ expectedRealm: Realm{ ++ addr: gno.DerivePkgAddr("gno.land/r/yyy").Bech32(), ++ pkgPath: "gno.land/r/yyy", ++ }, ++ expectedIsOriginCall: false, ++ }, ++ } ++ for _, tt := range tests { ++ t.Run(tt.name, func(t *testing.T) { ++ assert := assert.New(t) ++ ++ realm := prevRealm(tt.machine) ++ isOrigin := isOriginCall(tt.machine) ++ ++ assert.Equal(tt.expectedRealm, realm) ++ assert.Equal(tt.expectedIsOriginCall, isOrigin) ++ }) ++ } ++} +diff --git a/gnovm/stdlibs/stdlibs.go b/gnovm/stdlibs/stdlibs.go +index fb230a0cf8..2e73665a18 100644 +--- a/gnovm/stdlibs/stdlibs.go ++++ b/gnovm/stdlibs/stdlibs.go +@@ -151,8 +151,7 @@ func InjectPackage(store gno.Store, pn *gno.PackageNode) { + gno.Flds( // results + ), + func(m *gno.Machine) { +- isOrigin := len(m.Frames) == 2 +- if !isOrigin { ++ if !isOriginCall(m) { + m.Panic(typedString("invalid non-origin call")) + return + } +@@ -165,7 +164,7 @@ func InjectPackage(store gno.Store, pn *gno.PackageNode) { + "isOrigin", "bool", + ), + func(m *gno.Machine) { +- isOrigin := len(m.Frames) == 2 ++ isOrigin := isOriginCall(m) + res0 := gno.TypedValue{T: gno.BoolType} + res0.SetBool(isOrigin) + m.PushValue(res0) +@@ -308,47 +307,13 @@ func InjectPackage(store gno.Store, pn *gno.PackageNode) { + "", "Realm", + ), + func(m *gno.Machine) { +- var ( +- ctx = m.Context.(ExecContext) +- // Default lastCaller is OrigCaller, the signer of the tx +- lastCaller = ctx.OrigCaller +- lastPkgPath = "" +- ) +- +- for i := m.NumFrames() - 1; i > 0; i-- { +- fr := m.Frames[i] +- if fr.LastPackage == nil || !fr.LastPackage.IsRealm() { +- // Ignore non-realm frame +- continue +- } +- pkgPath := fr.LastPackage.PkgPath +- // The first realm we encounter will be the one calling +- // this function; to get the calling realm determine the first frame +- // where fr.LastPackage changes. +- if lastPkgPath == "" { +- lastPkgPath = pkgPath +- } else if lastPkgPath == pkgPath { +- continue +- } else { +- lastCaller = fr.LastPackage.GetPkgAddr().Bech32() +- lastPkgPath = pkgPath +- break +- } +- } +- +- // Empty the pkgPath if we return a user +- if ctx.OrigCaller == lastCaller { +- lastPkgPath = "" +- } ++ realm := prevRealm(m) + + // Return the result + res0 := gno.Go2GnoValue( + m.Alloc, + m.Store, +- reflect.ValueOf(Realm{ +- addr: lastCaller, +- pkgPath: lastPkgPath, +- }), ++ reflect.ValueOf(realm), + ) + + realmT := store.GetType(gno.DeclaredTypeID("std", "Realm")) +diff --git a/gnovm/tests/files/std9.gno b/gnovm/tests/files/std9.gno +deleted file mode 100644 +index 95ccfb2c8a..0000000000 +--- a/gnovm/tests/files/std9.gno ++++ /dev/null +@@ -1,14 +0,0 @@ +-package main +- +-import "std" +- +-func main() { +- defer func() { +- // assert panic is recoverable +- println(recover()) +- }() +- std.AssertOriginCall() +-} +- +-// Output: +-// invalid non-origin call +diff --git a/gnovm/tests/files/zrealm_tests0.gno b/gnovm/tests/files/zrealm_tests0.gno +index cfb1f08c6f..036e91b8a8 100644 +--- a/gnovm/tests/files/zrealm_tests0.gno ++++ b/gnovm/tests/files/zrealm_tests0.gno +@@ -245,7 +245,7 @@ func main() { + // "BlockNode": null, + // "Location": { + // "File": "tests.gno", +-// "Line": "42", ++// "Line": "50", + // "Nonce": "0", + // "PkgPath": "gno.land/r/demo/tests" + // } +@@ -301,7 +301,7 @@ func main() { + // "BlockNode": null, + // "Location": { + // "File": "tests.gno", +-// "Line": "42", ++// "Line": "50", + // "Nonce": "0", + // "PkgPath": "gno.land/r/demo/tests" + // } +@@ -734,6 +734,94 @@ func main() { + // { + // "T": { + // "@type": "/gno.FuncType", ++// "Params": [], ++// "Results": [] ++// }, ++// "V": { ++// "@type": "/gno.FuncValue", ++// "Closure": { ++// "@type": "/gno.RefValue", ++// "Escaped": true, ++// "ObjectID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:4" ++// }, ++// "FileName": "tests.gno", ++// "IsMethod": false, ++// "Name": "RSubtestsAssertOriginCall", ++// "PkgPath": "gno.land/r/demo/tests", ++// "Source": { ++// "@type": "/gno.RefNode", ++// "BlockNode": null, ++// "Location": { ++// "File": "tests.gno", ++// "Line": "31", ++// "Nonce": "0", ++// "PkgPath": "gno.land/r/demo/tests" ++// } ++// }, ++// "Type": { ++// "@type": "/gno.FuncType", ++// "Params": [], ++// "Results": [] ++// } ++// } ++// }, ++// { ++// "T": { ++// "@type": "/gno.FuncType", ++// "Params": [], ++// "Results": [ ++// { ++// "Embedded": false, ++// "Name": "", ++// "Tag": "", ++// "Type": { ++// "@type": "/gno.PrimitiveType", ++// "value": "4" ++// } ++// } ++// ] ++// }, ++// "V": { ++// "@type": "/gno.FuncValue", ++// "Closure": { ++// "@type": "/gno.RefValue", ++// "Escaped": true, ++// "ObjectID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:4" ++// }, ++// "FileName": "tests.gno", ++// "IsMethod": false, ++// "Name": "RSubtestsIsOriginCall", ++// "PkgPath": "gno.land/r/demo/tests", ++// "Source": { ++// "@type": "/gno.RefNode", ++// "BlockNode": null, ++// "Location": { ++// "File": "tests.gno", ++// "Line": "35", ++// "Nonce": "0", ++// "PkgPath": "gno.land/r/demo/tests" ++// } ++// }, ++// "Type": { ++// "@type": "/gno.FuncType", ++// "Params": [], ++// "Results": [ ++// { ++// "Embedded": false, ++// "Name": "", ++// "Tag": "", ++// "Type": { ++// "@type": "/gno.PrimitiveType", ++// "value": "4" ++// } ++// } ++// ] ++// } ++// } ++// }, ++// { ++// "T": { ++// "@type": "/gno.FuncType", + // "Params": [ + // { + // "Embedded": false, +@@ -766,7 +854,7 @@ func main() { + // "BlockNode": null, + // "Location": { + // "File": "tests.gno", +-// "Line": "38", ++// "Line": "46", + // "Nonce": "0", + // "PkgPath": "gno.land/r/demo/tests" + // } +@@ -813,7 +901,7 @@ func main() { + // "BlockNode": null, + // "Location": { + // "File": "tests.gno", +-// "Line": "60", ++// "Line": "68", + // "Nonce": "0", + // "PkgPath": "gno.land/r/demo/tests" + // } +@@ -847,7 +935,7 @@ func main() { + // "BlockNode": null, + // "Location": { + // "File": "tests.gno", +-// "Line": "65", ++// "Line": "73", + // "Nonce": "0", + // "PkgPath": "gno.land/r/demo/tests" + // } +@@ -881,7 +969,7 @@ func main() { + // "BlockNode": null, + // "Location": { + // "File": "tests.gno", +-// "Line": "73", ++// "Line": "81", + // "Nonce": "0", + // "PkgPath": "gno.land/r/demo/tests" + // } +@@ -925,7 +1013,7 @@ func main() { + // "BlockNode": null, + // "Location": { + // "File": "tests.gno", +-// "Line": "77", ++// "Line": "85", + // "Nonce": "0", + // "PkgPath": "gno.land/r/demo/tests" + // } +@@ -979,7 +1067,7 @@ func main() { + // "BlockNode": null, + // "Location": { + // "File": "tests.gno", +-// "Line": "81", ++// "Line": "89", + // "Nonce": "0", + // "PkgPath": "gno.land/r/demo/tests" + // } +@@ -1034,7 +1122,7 @@ func main() { + // "BlockNode": null, + // "Location": { + // "File": "tests.gno", +-// "Line": "85", ++// "Line": "93", + // "Nonce": "0", + // "PkgPath": "gno.land/r/demo/tests" + // } +diff --git a/gnovm/tests/imports.go b/gnovm/tests/imports.go +index fc2820ce00..f4ad1a8d3e 100644 +--- a/gnovm/tests/imports.go ++++ b/gnovm/tests/imports.go +@@ -471,22 +471,6 @@ func TestStore(rootDir, filesPath string, stdin io.Reader, stdout, stderr io.Wri + func testPackageInjector(store gno.Store, pn *gno.PackageNode) { + // Also inject stdlibs native functions. + stdlibs.InjectPackage(store, pn) +- isOriginCall := func(m *gno.Machine) bool { +- tname := m.Frames[0].Func.Name +- switch tname { +- case "main": // test is a _filetest +- return len(m.Frames) == 3 +- case "runtest": // test is a _test +- return len(m.Frames) == 7 +- } +- // support init() in _filetest +- // XXX do we need to distinguish from 'runtest'/_test? +- // XXX pretty hacky even if not. +- if strings.HasPrefix(string(tname), "init.") { +- return len(m.Frames) == 3 +- } +- panic("unable to determine if test is a _test or a _filetest") +- } + // Test specific injections: + switch pn.PkgPath { + case "strconv": +@@ -497,34 +481,6 @@ func testPackageInjector(store gno.Store, pn *gno.PackageNode) { + case "std": + // NOTE: some of these are overrides. + // Also see stdlibs/InjectPackage. +- pn.DefineNativeOverride("AssertOriginCall", +- /* +- gno.Flds( // params +- ), +- gno.Flds( // results +- ), +- */ +- func(m *gno.Machine) { +- if !isOriginCall(m) { +- m.Panic(typedString("invalid non-origin call")) +- return +- } +- }, +- ) +- pn.DefineNativeOverride("IsOriginCall", +- /* +- gno.Flds( // params +- ), +- gno.Flds( // results +- "isOrigin", "bool", +- ), +- */ +- func(m *gno.Machine) { +- res0 := gno.TypedValue{T: gno.BoolType} +- res0.SetBool(isOriginCall(m)) +- m.PushValue(res0) +- }, +- ) + pn.DefineNativeOverride("GetCallerAt", + /* + gno.Flds( // params diff --git a/util/gnolanddev/run.sh b/util/gnolanddev/run.sh new file mode 100755 index 00000000..f630ecca --- /dev/null +++ b/util/gnolanddev/run.sh @@ -0,0 +1,26 @@ +#!/bin/bash +set -eu + +rm -rf "$GNOROOT/gno.land" +mkdir -p "$GNOROOT" +cd "$GNOROOT" + +echo "copying stdlibs and examples from source..." +mkdir -p "$GNOROOT/gnovm" +rsync -a /opt/gno/src/gnovm/stdlibs "$GNOROOT/gnovm/" +rsync -a --delete /opt/gno/src/examples "$GNOROOT/" + +for gm in $(find /mnt -name 'gno.mod'); do + pkgpath="$(sed -n 's/^module \(.*\)$/\1/gp' "$gm")" + echo "adding module $pkgpath..." + mkdir -p "$GNOROOT/examples/$pkgpath" + # more conservative flags to avoid issues with entr. + rsync -a --delete --inplace "$(dirname "$gm")/" "$GNOROOT/examples/$pkgpath" +done + +mkdir -p gno.land/testdir/config gno.land/genesis +cp /opt/gno/src/gno.land/testdir/config/config.toml gno.land/testdir/config/ +rsync -ap /opt/gno/src/gno.land/genesis/ gno.land/genesis/ +echo "starting gnoland" +cd gno.land +gnoland start -genesis-max-vm-cycles 100''000''000 diff --git a/util/gnolanddev/strconv/decimal.gno b/util/gnolanddev/strconv/decimal.gno new file mode 100644 index 00000000..b5800188 --- /dev/null +++ b/util/gnolanddev/strconv/decimal.gno @@ -0,0 +1,415 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Multiprecision decimal numbers. +// For floating-point formatting only; not general purpose. +// Only operations are assign and (binary) left/right shift. +// Can do binary floating point in multiprecision decimal precisely +// because 2 divides 10; cannot do decimal floating point +// in multiprecision binary precisely. + +package strconv + +type decimal struct { + d [800]byte // digits, big-endian representation + nd int // number of digits used + dp int // decimal point + neg bool // negative flag + trunc bool // discarded nonzero digits beyond d[:nd] +} + +func (a *decimal) String() string { + n := 10 + a.nd + if a.dp > 0 { + n += a.dp + } + if a.dp < 0 { + n += -a.dp + } + + buf := make([]byte, n) + w := 0 + switch { + case a.nd == 0: + return "0" + + case a.dp <= 0: + // zeros fill space between decimal point and digits + buf[w] = '0' + w++ + buf[w] = '.' + w++ + w += digitZero(buf[w : w+-a.dp]) + w += copy(buf[w:], a.d[0:a.nd]) + + case a.dp < a.nd: + // decimal point in middle of digits + w += copy(buf[w:], a.d[0:a.dp]) + buf[w] = '.' + w++ + w += copy(buf[w:], a.d[a.dp:a.nd]) + + default: + // zeros fill space between digits and decimal point + w += copy(buf[w:], a.d[0:a.nd]) + w += digitZero(buf[w : w+a.dp-a.nd]) + } + return string(buf[0:w]) +} + +func digitZero(dst []byte) int { + for i := range dst { + dst[i] = '0' + } + return len(dst) +} + +// trim trailing zeros from number. +// (They are meaningless; the decimal point is tracked +// independent of the number of digits.) +func trim(a *decimal) { + for a.nd > 0 && a.d[a.nd-1] == '0' { + a.nd-- + } + if a.nd == 0 { + a.dp = 0 + } +} + +// Assign v to a. +func (a *decimal) Assign(v uint64) { + var buf [24]byte + + // Write reversed decimal in buf. + n := 0 + for v > 0 { + v1 := v / 10 + v -= 10 * v1 + buf[n] = byte(v + '0') + n++ + v = v1 + } + + // Reverse again to produce forward decimal in a.d. + a.nd = 0 + for n--; n >= 0; n-- { + a.d[a.nd] = buf[n] + a.nd++ + } + a.dp = a.nd + trim(a) +} + +// Maximum shift that we can do in one pass without overflow. +// A uint has 32 or 64 bits, and we have to be able to accommodate 9<> 63) +const maxShift = uintSize - 4 + +// Binary shift right (/ 2) by k bits. k <= maxShift to avoid overflow. +func rightShift(a *decimal, k uint) { + r := 0 // read pointer + w := 0 // write pointer + + // Pick up enough leading digits to cover first shift. + var n uint + for ; n>>k == 0; r++ { + if r >= a.nd { + if n == 0 { + // a == 0; shouldn't get here, but handle anyway. + a.nd = 0 + return + } + for n>>k == 0 { + n = n * 10 + r++ + } + break + } + c := uint(a.d[r]) + n = n*10 + c - '0' + } + a.dp -= r - 1 + + var mask uint = (1 << k) - 1 + + // Pick up a digit, put down a digit. + for ; r < a.nd; r++ { + c := uint(a.d[r]) + dig := n >> k + n &= mask + a.d[w] = byte(dig + '0') + w++ + n = n*10 + c - '0' + } + + // Put down extra digits. + for n > 0 { + dig := n >> k + n &= mask + if w < len(a.d) { + a.d[w] = byte(dig + '0') + w++ + } else if dig > 0 { + a.trunc = true + } + n = n * 10 + } + + a.nd = w + trim(a) +} + +// Cheat sheet for left shift: table indexed by shift count giving +// number of new digits that will be introduced by that shift. +// +// For example, leftcheats[4] = {2, "625"}. That means that +// if we are shifting by 4 (multiplying by 16), it will add 2 digits +// when the string prefix is "625" through "999", and one fewer digit +// if the string prefix is "000" through "624". +// +// Credit for this trick goes to Ken. + +type leftCheat struct { + delta int // number of new digits + cutoff string // minus one digit if original < a. +} + +var leftcheats = []leftCheat{ + // Leading digits of 1/2^i = 5^i. + // 5^23 is not an exact 64-bit floating point number, + // so have to use bc for the math. + // Go up to 60 to be large enough for 32bit and 64bit platforms. + /* + seq 60 | sed 's/^/5^/' | bc | + awk 'BEGIN{ print "\t{ 0, \"\" }," } + { + log2 = log(2)/log(10) + printf("\t{ %d, \"%s\" },\t// * %d\n", + int(log2*NR+1), $0, 2**NR) + }' + */ + {0, ""}, + {1, "5"}, // * 2 + {1, "25"}, // * 4 + {1, "125"}, // * 8 + {2, "625"}, // * 16 + {2, "3125"}, // * 32 + {2, "15625"}, // * 64 + {3, "78125"}, // * 128 + {3, "390625"}, // * 256 + {3, "1953125"}, // * 512 + {4, "9765625"}, // * 1024 + {4, "48828125"}, // * 2048 + {4, "244140625"}, // * 4096 + {4, "1220703125"}, // * 8192 + {5, "6103515625"}, // * 16384 + {5, "30517578125"}, // * 32768 + {5, "152587890625"}, // * 65536 + {6, "762939453125"}, // * 131072 + {6, "3814697265625"}, // * 262144 + {6, "19073486328125"}, // * 524288 + {7, "95367431640625"}, // * 1048576 + {7, "476837158203125"}, // * 2097152 + {7, "2384185791015625"}, // * 4194304 + {7, "11920928955078125"}, // * 8388608 + {8, "59604644775390625"}, // * 16777216 + {8, "298023223876953125"}, // * 33554432 + {8, "1490116119384765625"}, // * 67108864 + {9, "7450580596923828125"}, // * 134217728 + {9, "37252902984619140625"}, // * 268435456 + {9, "186264514923095703125"}, // * 536870912 + {10, "931322574615478515625"}, // * 1073741824 + {10, "4656612873077392578125"}, // * 2147483648 + {10, "23283064365386962890625"}, // * 4294967296 + {10, "116415321826934814453125"}, // * 8589934592 + {11, "582076609134674072265625"}, // * 17179869184 + {11, "2910383045673370361328125"}, // * 34359738368 + {11, "14551915228366851806640625"}, // * 68719476736 + {12, "72759576141834259033203125"}, // * 137438953472 + {12, "363797880709171295166015625"}, // * 274877906944 + {12, "1818989403545856475830078125"}, // * 549755813888 + {13, "9094947017729282379150390625"}, // * 1099511627776 + {13, "45474735088646411895751953125"}, // * 2199023255552 + {13, "227373675443232059478759765625"}, // * 4398046511104 + {13, "1136868377216160297393798828125"}, // * 8796093022208 + {14, "5684341886080801486968994140625"}, // * 17592186044416 + {14, "28421709430404007434844970703125"}, // * 35184372088832 + {14, "142108547152020037174224853515625"}, // * 70368744177664 + {15, "710542735760100185871124267578125"}, // * 140737488355328 + {15, "3552713678800500929355621337890625"}, // * 281474976710656 + {15, "17763568394002504646778106689453125"}, // * 562949953421312 + {16, "88817841970012523233890533447265625"}, // * 1125899906842624 + {16, "444089209850062616169452667236328125"}, // * 2251799813685248 + {16, "2220446049250313080847263336181640625"}, // * 4503599627370496 + {16, "11102230246251565404236316680908203125"}, // * 9007199254740992 + {17, "55511151231257827021181583404541015625"}, // * 18014398509481984 + {17, "277555756156289135105907917022705078125"}, // * 36028797018963968 + {17, "1387778780781445675529539585113525390625"}, // * 72057594037927936 + {18, "6938893903907228377647697925567626953125"}, // * 144115188075855872 + {18, "34694469519536141888238489627838134765625"}, // * 288230376151711744 + {18, "173472347597680709441192448139190673828125"}, // * 576460752303423488 + {19, "867361737988403547205962240695953369140625"}, // * 1152921504606846976 +} + +// Is the leading prefix of b lexicographically less than s? +func prefixIsLessThan(b []byte, s string) bool { + for i := 0; i < len(s); i++ { + if i >= len(b) { + return true + } + if b[i] != s[i] { + return b[i] < s[i] + } + } + return false +} + +// Binary shift left (* 2) by k bits. k <= maxShift to avoid overflow. +func leftShift(a *decimal, k uint) { + delta := leftcheats[k].delta + if prefixIsLessThan(a.d[0:a.nd], leftcheats[k].cutoff) { + delta-- + } + + r := a.nd // read index + w := a.nd + delta // write index + + // Pick up a digit, put down a digit. + var n uint + for r--; r >= 0; r-- { + n += (uint(a.d[r]) - '0') << k + quo := n / 10 + rem := n - 10*quo + w-- + if w < len(a.d) { + a.d[w] = byte(rem + '0') + } else if rem != 0 { + a.trunc = true + } + n = quo + } + + // Put down extra digits. + for n > 0 { + quo := n / 10 + rem := n - 10*quo + w-- + if w < len(a.d) { + a.d[w] = byte(rem + '0') + } else if rem != 0 { + a.trunc = true + } + n = quo + } + + a.nd += delta + if a.nd >= len(a.d) { + a.nd = len(a.d) + } + a.dp += delta + trim(a) +} + +// Binary shift left (k > 0) or right (k < 0). +func (a *decimal) Shift(k int) { + switch { + case a.nd == 0: + // nothing to do: a == 0 + case k > 0: + for k > maxShift { + leftShift(a, maxShift) + k -= maxShift + } + leftShift(a, uint(k)) + case k < 0: + for k < -maxShift { + rightShift(a, maxShift) + k += maxShift + } + rightShift(a, uint(-k)) + } +} + +// If we chop a at nd digits, should we round up? +func shouldRoundUp(a *decimal, nd int) bool { + if nd < 0 || nd >= a.nd { + return false + } + if a.d[nd] == '5' && nd+1 == a.nd { // exactly halfway - round to even + // if we truncated, a little higher than what's recorded - always round up + if a.trunc { + return true + } + return nd > 0 && (a.d[nd-1]-'0')%2 != 0 + } + // not halfway - digit tells all + return a.d[nd] >= '5' +} + +// Round a to nd digits (or fewer). +// If nd is zero, it means we're rounding +// just to the left of the digits, as in +// 0.09 -> 0.1. +func (a *decimal) Round(nd int) { + if nd < 0 || nd >= a.nd { + return + } + if shouldRoundUp(a, nd) { + a.RoundUp(nd) + } else { + a.RoundDown(nd) + } +} + +// Round a down to nd digits (or fewer). +func (a *decimal) RoundDown(nd int) { + if nd < 0 || nd >= a.nd { + return + } + a.nd = nd + trim(a) +} + +// Round a up to nd digits (or fewer). +func (a *decimal) RoundUp(nd int) { + if nd < 0 || nd >= a.nd { + return + } + + // round up + for i := nd - 1; i >= 0; i-- { + c := a.d[i] + if c < '9' { // can stop after this digit + a.d[i]++ + a.nd = i + 1 + return + } + } + + // Number is all 9s. + // Change to single 1 with adjusted decimal point. + a.d[0] = '1' + a.nd = 1 + a.dp++ +} + +// Extract integer part, rounded appropriately. +// No guarantees about overflow. +func (a *decimal) RoundedInteger() uint64 { + if a.dp > 20 { + return 0xFFFFFFFFFFFFFFFF + } + var i int + n := uint64(0) + for i = 0; i < a.dp && i < a.nd; i++ { + n = n*10 + uint64(a.d[i]-'0') + } + for ; i < a.dp; i++ { + n *= 10 + } + if shouldRoundUp(a, a.dp) { + n++ + } + return n +} diff --git a/util/gnolanddev/strconv/decimal_test.gno b/util/gnolanddev/strconv/decimal_test.gno new file mode 100644 index 00000000..b7dcce7c --- /dev/null +++ b/util/gnolanddev/strconv/decimal_test.gno @@ -0,0 +1,126 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package strconv + +import ( + "testing" +) + +type shiftTest struct { + i uint64 + shift int + out string +} + +var shifttests = []shiftTest{ + {0, -100, "0"}, + {0, 100, "0"}, + {1, 100, "1267650600228229401496703205376"}, + {1, -100, + "0.00000000000000000000000000000078886090522101180541" + + "17285652827862296732064351090230047702789306640625", + }, + {12345678, 8, "3160493568"}, + {12345678, -8, "48225.3046875"}, + {195312, 9, "99999744"}, + {1953125, 9, "1000000000"}, +} + +func TestDecimalShift(t *testing.T) { + for i := 0; i < len(shifttests); i++ { + test := &shifttests[i] + d := NewDecimal(test.i) + d.Shift(test.shift) + s := d.String() + if s != test.out { + t.Errorf("Decimal %v << %v = %v, want %v", + test.i, test.shift, s, test.out) + } + } +} + +type roundTest struct { + i uint64 + nd int + down, round, up string + int uint64 +} + +var roundtests = []roundTest{ + {0, 4, "0", "0", "0", 0}, + {12344999, 4, "12340000", "12340000", "12350000", 12340000}, + {12345000, 4, "12340000", "12340000", "12350000", 12340000}, + {12345001, 4, "12340000", "12350000", "12350000", 12350000}, + {23454999, 4, "23450000", "23450000", "23460000", 23450000}, + {23455000, 4, "23450000", "23460000", "23460000", 23460000}, + {23455001, 4, "23450000", "23460000", "23460000", 23460000}, + + {99994999, 4, "99990000", "99990000", "100000000", 99990000}, + {99995000, 4, "99990000", "100000000", "100000000", 100000000}, + {99999999, 4, "99990000", "100000000", "100000000", 100000000}, + + {12994999, 4, "12990000", "12990000", "13000000", 12990000}, + {12995000, 4, "12990000", "13000000", "13000000", 13000000}, + {12999999, 4, "12990000", "13000000", "13000000", 13000000}, +} + +func TestDecimalRound(t *testing.T) { + for i := 0; i < len(roundtests); i++ { + test := &roundtests[i] + d := NewDecimal(test.i) + d.RoundDown(test.nd) + s := d.String() + if s != test.down { + t.Errorf("Decimal %v RoundDown %d = %v, want %v", + test.i, test.nd, s, test.down) + } + d = NewDecimal(test.i) + d.Round(test.nd) + s = d.String() + if s != test.round { + t.Errorf("Decimal %v Round %d = %v, want %v", + test.i, test.nd, s, test.down) + } + d = NewDecimal(test.i) + d.RoundUp(test.nd) + s = d.String() + if s != test.up { + t.Errorf("Decimal %v RoundUp %d = %v, want %v", + test.i, test.nd, s, test.up) + } + } +} + +type roundIntTest struct { + i uint64 + shift int + int uint64 +} + +var roundinttests = []roundIntTest{ + {0, 100, 0}, + {512, -8, 2}, + {513, -8, 2}, + {640, -8, 2}, + {641, -8, 3}, + {384, -8, 2}, + {385, -8, 2}, + {383, -8, 1}, + {1, 100, 1<<64 - 1}, + {1000, 0, 1000}, +} + +func TestDecimalRoundedInteger(t *testing.T) { + for i := 0; i < len(roundinttests); i++ { + test := roundinttests[i] + d := NewDecimal(test.i) + d.Shift(test.shift) + int := d.RoundedInteger() + if int != test.int { + t.Errorf("Decimal %v >> %v RoundedInteger = %v, want %v", + test.i, test.shift, int, test.int) + } + } +} diff --git a/util/gnolanddev/strconv/ftoa.gno b/util/gnolanddev/strconv/ftoa.gno new file mode 100644 index 00000000..da71b1d7 --- /dev/null +++ b/util/gnolanddev/strconv/ftoa.gno @@ -0,0 +1,702 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Binary to decimal floating point conversion. +// Algorithm: +// 1) store mantissa in multiprecision decimal +// 2) shift decimal by exponent +// 3) read digits out & format + +package strconv + +import ( + "math" + "math/bits" +) + +// TODO: move elsewhere? +type floatInfo struct { + mantbits uint + expbits uint + bias int +} + +var float32info = floatInfo{23, 8, -127} +var float64info = floatInfo{52, 11, -1023} + +// FormatFloat converts the floating-point number f to a string, +// according to the format fmt and precision prec. It rounds the +// result assuming that the original was obtained from a floating-point +// value of bitSize bits (32 for float32, 64 for float64). +// +// The format fmt is one of +// 'b' (-ddddp±ddd, a binary exponent), +// 'e' (-d.dddde±dd, a decimal exponent), +// 'E' (-d.ddddE±dd, a decimal exponent), +// 'f' (-ddd.dddd, no exponent), +// 'g' ('e' for large exponents, 'f' otherwise), +// 'G' ('E' for large exponents, 'f' otherwise), +// 'x' (-0xd.ddddp±ddd, a hexadecimal fraction and binary exponent), or +// 'X' (-0Xd.ddddP±ddd, a hexadecimal fraction and binary exponent). +// +// The precision prec controls the number of digits (excluding the exponent) +// printed by the 'e', 'E', 'f', 'g', 'G', 'x', and 'X' formats. +// For 'e', 'E', 'f', 'x', and 'X', it is the number of digits after the decimal point. +// For 'g' and 'G' it is the maximum number of significant digits (trailing +// zeros are removed). +// The special precision -1 uses the smallest number of digits +// necessary such that ParseFloat will return f exactly. +func FormatFloat(f float64, fmt byte, prec, bitSize int) string { + return string(genericFtoa(make([]byte, 0, max(prec+4, 24)), f, fmt, prec, bitSize)) +} + +// AppendFloat appends the string form of the floating-point number f, +// as generated by FormatFloat, to dst and returns the extended buffer. +func AppendFloat(dst []byte, f float64, fmt byte, prec, bitSize int) []byte { + return genericFtoa(dst, f, fmt, prec, bitSize) +} + +func genericFtoa(dst []byte, val float64, fmt byte, prec, bitSize int) []byte { + var bits uint64 + var flt *floatInfo + switch bitSize { + case 32: + bits = uint64(math.Float32bits(float32(val))) + flt = &float32info + case 64: + bits = math.Float64bits(val) + flt = &float64info + default: + panic("strconv: illegal AppendFloat/FormatFloat bitSize") + } + + neg := bits>>(flt.expbits+flt.mantbits) != 0 + exp := int(bits>>flt.mantbits) & (1< digs.nd && digs.nd >= digs.dp { + eprec = digs.nd + } + // %e is used if the exponent from the conversion + // is less than -4 or greater than or equal to the precision. + // if precision was the shortest possible, use precision 6 for this decision. + if shortest { + eprec = 6 + } + exp := digs.dp - 1 + if exp < -4 || exp >= eprec { + if prec > digs.nd { + prec = digs.nd + } + return fmtE(dst, neg, digs, prec-1, fmt+'e'-'g') + } + if prec > digs.dp { + prec = digs.nd + } + return fmtF(dst, neg, digs, max(prec-digs.dp, 0)) + } + + // unknown format + return append(dst, byte('%'), fmt) +} + +// roundShortest rounds d (= mant * 2^exp) to the shortest number of digits +// that will let the original floating point value be precisely reconstructed. +func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) { + // If mantissa is zero, the number is zero; stop now. + if mant == 0 { + d.nd = 0 + return + } + + // Compute upper and lower such that any decimal number + // between upper and lower (possibly inclusive) + // will round to the original floating point number. + + // We may see at once that the number is already shortest. + // + // Suppose d is not denormal, so that 2^exp <= d < 10^dp. + // The closest shorter number is at least 10^(dp-nd) away. + // The lower/upper bounds computed below are at distance + // at most 2^(exp-mantbits). + // + // So the number is already shortest if 10^(dp-nd) > 2^(exp-mantbits), + // or equivalently log2(10)*(dp-nd) > exp-mantbits. + // It is true if 332/100*(dp-nd) >= exp-mantbits (log2(10) > 3.32). + minexp := flt.bias + 1 // minimum possible exponent + if exp > minexp && 332*(d.dp-d.nd) >= 100*(exp-int(flt.mantbits)) { + // The number is already shortest. + return + } + + // d = mant << (exp - mantbits) + // Next highest floating point number is mant+1 << exp-mantbits. + // Our upper bound is halfway between, mant*2+1 << exp-mantbits-1. + upper := new(decimal) + upper.Assign(mant*2 + 1) + upper.Shift(exp - int(flt.mantbits) - 1) + + // d = mant << (exp - mantbits) + // Next lowest floating point number is mant-1 << exp-mantbits, + // unless mant-1 drops the significant bit and exp is not the minimum exp, + // in which case the next lowest is mant*2-1 << exp-mantbits-1. + // Either way, call it mantlo << explo-mantbits. + // Our lower bound is halfway between, mantlo*2+1 << explo-mantbits-1. + var mantlo uint64 + var explo int + if mant > 1<= d.nd { + break + } + li := ui - upper.dp + lower.dp + l := byte('0') // lower digit + if li >= 0 && li < lower.nd { + l = lower.d[li] + } + m := byte('0') // middle digit + if mi >= 0 { + m = d.d[mi] + } + u := byte('0') // upper digit + if ui < upper.nd { + u = upper.d[ui] + } + + // Okay to round down (truncate) if lower has a different digit + // or if lower is inclusive and is exactly the result of rounding + // down (i.e., and we have reached the final digit of lower). + okdown := l != m || inclusive && li+1 == lower.nd + + switch { + case upperdelta == 0 && m+1 < u: + // Example: + // m = 12345xxx + // u = 12347xxx + upperdelta = 2 + case upperdelta == 0 && m != u: + // Example: + // m = 12345xxx + // u = 12346xxx + upperdelta = 1 + case upperdelta == 1 && (m != '9' || u != '0'): + // Example: + // m = 1234598x + // u = 1234600x + upperdelta = 2 + } + // Okay to round up if upper has a different digit and either upper + // is inclusive or upper is bigger than the result of rounding up. + okup := upperdelta > 0 && (inclusive || upperdelta > 1 || ui+1 < upper.nd) + + // If it's okay to do either, then round to the nearest one. + // If it's okay to do only one, do it. + switch { + case okdown && okup: + d.Round(mi + 1) + return + case okdown: + d.RoundDown(mi + 1) + return + case okup: + d.RoundUp(mi + 1) + return + } + } +} + +type decimalSlice struct { + d []byte + nd, dp int +} + +// %e: -d.ddddde±dd +func fmtE(dst []byte, neg bool, d decimalSlice, prec int, fmt byte) []byte { + // sign + if neg { + dst = append(dst, '-') + } + + // first digit + ch := byte('0') + if d.nd != 0 { + ch = d.d[0] + } + dst = append(dst, ch) + + // .moredigits + if prec > 0 { + dst = append(dst, '.') + i := 1 + m := min(d.nd, prec+1) + if i < m { + dst = append(dst, d.d[i:m]...) + i = m + } + for ; i <= prec; i++ { + dst = append(dst, '0') + } + } + + // e± + dst = append(dst, fmt) + exp := d.dp - 1 + if d.nd == 0 { // special case: 0 has exponent 0 + exp = 0 + } + if exp < 0 { + ch = '-' + exp = -exp + } else { + ch = '+' + } + dst = append(dst, ch) + + // dd or ddd + switch { + case exp < 10: + dst = append(dst, byte('0'), byte(exp)+'0') + case exp < 100: + dst = append(dst, byte(exp/10)+'0', byte(exp%10)+'0') + default: + dst = append(dst, byte(exp/100)+'0', byte(exp/10)%10+'0', byte(exp%10)+'0') + } + + return dst +} + +// %f: -ddddddd.ddddd +func fmtF(dst []byte, neg bool, d decimalSlice, prec int) []byte { + // sign + if neg { + dst = append(dst, '-') + } + + // integer, padded with zeros as needed. + if d.dp > 0 { + m := min(d.nd, d.dp) + dst = append(dst, d.d[:m]...) + for ; m < d.dp; m++ { + dst = append(dst, '0') + } + } else { + dst = append(dst, '0') + } + + // fraction + if prec > 0 { + dst = append(dst, '.') + for i := 0; i < prec; i++ { + ch := byte('0') + if j := d.dp + i; 0 <= j && j < d.nd { + ch = d.d[j] + } + dst = append(dst, ch) + } + } + + return dst +} + +// %b: -ddddddddp±ddd +func fmtB(dst []byte, neg bool, mant uint64, exp int, flt *floatInfo) []byte { + // sign + if neg { + dst = append(dst, '-') + } + + // mantissa + dst, _ = formatBits(dst, mant, 10, false, true) + + // p + dst = append(dst, 'p') + + // ±exponent + exp -= int(flt.mantbits) + if exp >= 0 { + dst = append(dst, '+') + } + dst, _ = formatBits(dst, uint64(exp), 10, exp < 0, true) + + return dst +} + +// %x: -0x1.yyyyyyyyp±ddd or -0x0p+0. (y is hex digit, d is decimal digit) +func fmtX(dst []byte, prec int, fmt byte, neg bool, mant uint64, exp int, flt *floatInfo) []byte { + if mant == 0 { + exp = 0 + } + + // Shift digits so leading 1 (if any) is at bit 1<<60. + mant <<= 60 - flt.mantbits + for mant != 0 && mant&(1<<60) == 0 { + mant <<= 1 + exp-- + } + + // Round if requested. + if prec >= 0 && prec < 15 { + shift := uint(prec * 4) + extra := (mant << shift) & (1<<60 - 1) + mant >>= 60 - shift + if extra|(mant&1) > 1<<59 { + mant++ + } + mant <<= 60 - shift + if mant&(1<<61) != 0 { + // Wrapped around. + mant >>= 1 + exp++ + } + } + + hex := lowerhex + if fmt == 'X' { + hex = upperhex + } + + // sign, 0x, leading digit + if neg { + dst = append(dst, '-') + } + dst = append(dst, byte('0'), fmt, '0'+byte((mant>>60)&1)) + + // .fraction + mant <<= 4 // remove leading 0 or 1 + if prec < 0 && mant != 0 { + dst = append(dst, '.') + for mant != 0 { + dst = append(dst, hex[(mant>>60)&15]) + mant <<= 4 + } + } else if prec > 0 { + dst = append(dst, '.') + for i := 0; i < prec; i++ { + dst = append(dst, hex[(mant>>60)&15]) + mant <<= 4 + } + } + + // p± + ch := byte('P') + if fmt == lower(fmt) { + ch = 'p' + } + dst = append(dst, ch) + if exp < 0 { + ch = '-' + exp = -exp + } else { + ch = '+' + } + dst = append(dst, ch) + + // dd or ddd or dddd + switch { + case exp < 100: + dst = append(dst, byte(exp/10)+'0', byte(exp%10)+'0') + case exp < 1000: + dst = append(dst, byte(exp/100)+'0', byte((exp/10)%10)+'0', byte(exp%10)+'0') + default: + dst = append(dst, byte(exp/1000)+'0', byte(exp/100)%10+'0', byte((exp/10)%10)+'0', byte(exp%10)+'0') + } + + return dst +} + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +// formatBits computes the string representation of u in the given base. +// If neg is set, u is treated as negative int64 value. If append_ is +// set, the string is appended to dst and the resulting byte slice is +// returned as the first result value; otherwise the string is returned +// as the second result value. +func formatBits(dst []byte, u uint64, base int, neg, append_ bool) (d []byte, s string) { + if base < 2 || base > len(digits) { + panic("strconv: illegal AppendInt/FormatInt base") + } + // 2 <= base && base <= len(digits) + + var a [64 + 1]byte // +1 for sign of 64bit value in base 2 + i := len(a) + + if neg { + u = -u + } + + // convert bits + // We use uint values where we can because those will + // fit into a single register even on a 32bit machine. + if base == 10 { + // common case: use constants for / because + // the compiler can optimize it into a multiply+shift + + // u guaranteed to fit into a uint + us := uint(u) + for us >= 100 { + is := us % 100 * 2 + us /= 100 + i -= 2 + a[i+1] = smallsString[is+1] + a[i+0] = smallsString[is+0] + } + + // us < 100 + is := us * 2 + i-- + a[i] = smallsString[is+1] + if us >= 10 { + i-- + a[i] = smallsString[is] + } + + } else if isPowerOfTwo(base) { + // Use shifts and masks instead of / and %. + // Base is a power of 2 and 2 <= base <= len(digits) where len(digits) is 36. + // The largest power of 2 below or equal to 36 is 32, which is 1 << 5; + // i.e., the largest possible shift count is 5. By &-ind that value with + // the constant 7 we tell the compiler that the shift count is always + // less than 8 which is smaller than any register width. This allows + // the compiler to generate better code for the shift operation. + shift := uint(bits.TrailingZeros(uint(base))) & 7 + b := uint64(base) + m := uint(base) - 1 // == 1<= b { + i-- + a[i] = digits[uint(u)&m] + u >>= shift + } + // u < base + i-- + a[i] = digits[uint(u)] + } else { + // general case + b := uint64(base) + for u >= b { + i-- + // Avoid using r = a%b in addition to q = a/b + // since 64bit division and modulo operations + // are calculated by runtime functions on 32bit machines. + q := u / b + a[i] = digits[uint(u-q*b)] + u = q + } + // u < base + i-- + a[i] = digits[uint(u)] + } + + // add sign, if any + if neg { + i-- + a[i] = '-' + } + + if append_ { + d = append(dst, a[i:]...) + return + } + s = string(a[i:]) + return +} + +const ( + lowerhex = "0123456789abcdef" + upperhex = "0123456789ABCDEF" +) + +func lower(c byte) byte { + return c | ('x' - 'X') +} + +const digits = "0123456789abcdefghijklmnopqrstuvwxyz" +const smallsString = "00010203040506070809" + + "10111213141516171819" + + "20212223242526272829" + + "30313233343536373839" + + "40414243444546474849" + + "50515253545556575859" + + "60616263646566676869" + + "70717273747576777879" + + "80818283848586878889" + + "90919293949596979899" + +func isPowerOfTwo(x int) bool { + return x&(x-1) == 0 +} diff --git a/util/gnolanddev/strconv/ftoa_test.gno b/util/gnolanddev/strconv/ftoa_test.gno new file mode 100644 index 00000000..7713f0d7 --- /dev/null +++ b/util/gnolanddev/strconv/ftoa_test.gno @@ -0,0 +1,275 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package strconv + +import ( + "math" + "math/rand" + "testing" +) + +type ftoaTest struct { + f float64 + fmt byte + prec int + s string +} + +func fdiv(a, b float64) float64 { return a / b } + +const ( + below1e23 = 99999999999999974834176 + above1e23 = 100000000000000008388608 +) + +var ftoatests = []ftoaTest{ + {1, 'e', 5, "1.00000e+00"}, + {1, 'f', 5, "1.00000"}, + {1, 'g', 5, "1"}, + {1, 'g', -1, "1"}, + {1, 'x', -1, "0x1p+00"}, + {1, 'x', 5, "0x1.00000p+00"}, + {20, 'g', -1, "20"}, + {20, 'x', -1, "0x1.4p+04"}, + {1234567.8, 'g', -1, "1.2345678e+06"}, + {1234567.8, 'x', -1, "0x1.2d687cccccccdp+20"}, + {200000, 'g', -1, "200000"}, + {200000, 'x', -1, "0x1.86ap+17"}, + {200000, 'X', -1, "0X1.86AP+17"}, + {2000000, 'g', -1, "2e+06"}, + {1e10, 'g', -1, "1e+10"}, + + // g conversion and zero suppression + {400, 'g', 2, "4e+02"}, + {40, 'g', 2, "40"}, + {4, 'g', 2, "4"}, + {.4, 'g', 2, "0.4"}, + {.04, 'g', 2, "0.04"}, + {.004, 'g', 2, "0.004"}, + {.0004, 'g', 2, "0.0004"}, + {.00004, 'g', 2, "4e-05"}, + {.000004, 'g', 2, "4e-06"}, + + {0, 'e', 5, "0.00000e+00"}, + {0, 'f', 5, "0.00000"}, + {0, 'g', 5, "0"}, + {0, 'g', -1, "0"}, + {0, 'x', 5, "0x0.00000p+00"}, + + {-1, 'e', 5, "-1.00000e+00"}, + {-1, 'f', 5, "-1.00000"}, + {-1, 'g', 5, "-1"}, + {-1, 'g', -1, "-1"}, + + {12, 'e', 5, "1.20000e+01"}, + {12, 'f', 5, "12.00000"}, + {12, 'g', 5, "12"}, + {12, 'g', -1, "12"}, + + {123456700, 'e', 5, "1.23457e+08"}, + {123456700, 'f', 5, "123456700.00000"}, + {123456700, 'g', 5, "1.2346e+08"}, + {123456700, 'g', -1, "1.234567e+08"}, + + {1.2345e6, 'e', 5, "1.23450e+06"}, + {1.2345e6, 'f', 5, "1234500.00000"}, + {1.2345e6, 'g', 5, "1.2345e+06"}, + + // Round to even + {1.2345e6, 'e', 3, "1.234e+06"}, + {1.2355e6, 'e', 3, "1.236e+06"}, + {1.2345, 'f', 3, "1.234"}, + {1.2355, 'f', 3, "1.236"}, + {1234567890123456.5, 'e', 15, "1.234567890123456e+15"}, + {1234567890123457.5, 'e', 15, "1.234567890123458e+15"}, + {108678236358137.625, 'g', -1, "1.0867823635813762e+14"}, + + {1e23, 'e', 17, "9.99999999999999916e+22"}, + {1e23, 'f', 17, "99999999999999991611392.00000000000000000"}, + {1e23, 'g', 17, "9.9999999999999992e+22"}, + + {1e23, 'e', -1, "1e+23"}, + {1e23, 'f', -1, "100000000000000000000000"}, + {1e23, 'g', -1, "1e+23"}, + + {below1e23, 'e', 17, "9.99999999999999748e+22"}, + {below1e23, 'f', 17, "99999999999999974834176.00000000000000000"}, + {below1e23, 'g', 17, "9.9999999999999975e+22"}, + + {below1e23, 'e', -1, "9.999999999999997e+22"}, + {below1e23, 'f', -1, "99999999999999970000000"}, + {below1e23, 'g', -1, "9.999999999999997e+22"}, + + {above1e23, 'e', 17, "1.00000000000000008e+23"}, + {above1e23, 'f', 17, "100000000000000008388608.00000000000000000"}, + {above1e23, 'g', 17, "1.0000000000000001e+23"}, + + {above1e23, 'e', -1, "1.0000000000000001e+23"}, + {above1e23, 'f', -1, "100000000000000010000000"}, + {above1e23, 'g', -1, "1.0000000000000001e+23"}, + + {fdiv(5e-304, 1e20), 'g', -1, "5e-324"}, // avoid constant arithmetic + {fdiv(-5e-304, 1e20), 'g', -1, "-5e-324"}, // avoid constant arithmetic + + {32, 'g', -1, "32"}, + {32, 'g', 0, "3e+01"}, + + {100, 'x', -1, "0x1.9p+06"}, + {100, 'y', -1, "%y"}, + + {math.NaN(), 'g', -1, "NaN"}, + {-math.NaN(), 'g', -1, "NaN"}, + {math.Inf(0), 'g', -1, "+Inf"}, + {math.Inf(-1), 'g', -1, "-Inf"}, + {-math.Inf(0), 'g', -1, "-Inf"}, + + {-1, 'b', -1, "-4503599627370496p-52"}, + + // fixed bugs + {0.9, 'f', 1, "0.9"}, + {0.09, 'f', 1, "0.1"}, + {0.0999, 'f', 1, "0.1"}, + {0.05, 'f', 1, "0.1"}, + {0.05, 'f', 0, "0"}, + {0.5, 'f', 1, "0.5"}, + {0.5, 'f', 0, "0"}, + {1.5, 'f', 0, "2"}, + + // https://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/ + {2.2250738585072012e-308, 'g', -1, "2.2250738585072014e-308"}, + // https://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/ + {2.2250738585072011e-308, 'g', -1, "2.225073858507201e-308"}, + + // Issue 2625. + {383260575764816448, 'f', 0, "383260575764816448"}, + {383260575764816448, 'g', -1, "3.8326057576481645e+17"}, + + // Issue 29491. + {498484681984085570, 'f', -1, "498484681984085570"}, + {-5.8339553793802237e+23, 'g', -1, "-5.8339553793802237e+23"}, + + // Issue 52187 + {123.45, '?', 0, "%?"}, + {123.45, '?', 1, "%?"}, + {123.45, '?', -1, "%?"}, + + // rounding + {2.275555555555555, 'x', -1, "0x1.23456789abcdep+01"}, + {2.275555555555555, 'x', 0, "0x1p+01"}, + {2.275555555555555, 'x', 2, "0x1.23p+01"}, + {2.275555555555555, 'x', 16, "0x1.23456789abcde000p+01"}, + {2.275555555555555, 'x', 21, "0x1.23456789abcde00000000p+01"}, + {2.2755555510520935, 'x', -1, "0x1.2345678p+01"}, + {2.2755555510520935, 'x', 6, "0x1.234568p+01"}, + {2.275555431842804, 'x', -1, "0x1.2345668p+01"}, + {2.275555431842804, 'x', 6, "0x1.234566p+01"}, + {3.999969482421875, 'x', -1, "0x1.ffffp+01"}, + {3.999969482421875, 'x', 4, "0x1.ffffp+01"}, + {3.999969482421875, 'x', 3, "0x1.000p+02"}, + {3.999969482421875, 'x', 2, "0x1.00p+02"}, + {3.999969482421875, 'x', 1, "0x1.0p+02"}, + {3.999969482421875, 'x', 0, "0x1p+02"}, +} + +func TestFtoa(t *testing.T) { + for i := 0; i < len(ftoatests); i++ { + test := &ftoatests[i] + s := FormatFloat(test.f, test.fmt, test.prec, 64) + if s != test.s { + t.Error("testN=64", test.f, string(test.fmt), test.prec, "want", test.s, "got", s) + } + x := AppendFloat([]byte("abc"), test.f, test.fmt, test.prec, 64) + if string(x) != "abc"+test.s { + t.Error("AppendFloat testN=64", test.f, string(test.fmt), test.prec, "want", "abc"+test.s, "got", string(x)) + } + if float64(float32(test.f)) == test.f && test.fmt != 'b' { + s := FormatFloat(test.f, test.fmt, test.prec, 32) + if s != test.s { + t.Error("testN=32", test.f, string(test.fmt), test.prec, "want", test.s, "got", s) + } + x := AppendFloat([]byte("abc"), test.f, test.fmt, test.prec, 32) + if string(x) != "abc"+test.s { + t.Error("AppendFloat testN=32", test.f, string(test.fmt), test.prec, "want", "abc"+test.s, "got", string(x)) + } + } + } +} + +func TestFormatFloatInvalidBitSize(t *testing.T) { + defer func() { + if r := recover(); r == nil { + t.Fatalf("expected panic due to invalid bitSize") + } + }() + _ = FormatFloat(3.14, 'g', -1, 100) +} + +var ftoaBenches = []struct { + name string + float float64 + fmt byte + prec int + bitSize int +}{ + {"Decimal", 33909, 'g', -1, 64}, + {"Float", 339.7784, 'g', -1, 64}, + {"Exp", -5.09e75, 'g', -1, 64}, + {"NegExp", -5.11e-95, 'g', -1, 64}, + {"LongExp", 1.234567890123456e-78, 'g', -1, 64}, + + {"Big", 123456789123456789123456789, 'g', -1, 64}, + {"BinaryExp", -1, 'b', -1, 64}, + + {"32Integer", 33909, 'g', -1, 32}, + {"32ExactFraction", 3.375, 'g', -1, 32}, + {"32Point", 339.7784, 'g', -1, 32}, + {"32Exp", -5.09e25, 'g', -1, 32}, + {"32NegExp", -5.11e-25, 'g', -1, 32}, + {"32Shortest", 1.234567e-8, 'g', -1, 32}, + {"32Fixed8Hard", math.Ldexp(15961084, -125), 'e', 8, 32}, + {"32Fixed9Hard", math.Ldexp(14855922, -83), 'e', 9, 32}, + + {"64Fixed1", 123456, 'e', 3, 64}, + {"64Fixed2", 123.456, 'e', 3, 64}, + {"64Fixed3", 1.23456e+78, 'e', 3, 64}, + {"64Fixed4", 1.23456e-78, 'e', 3, 64}, + {"64Fixed12", 1.23456e-78, 'e', 12, 64}, + {"64Fixed16", 1.23456e-78, 'e', 16, 64}, + // From testdata/testfp.txt + {"64Fixed12Hard", math.Ldexp(6965949469487146, -249), 'e', 12, 64}, + {"64Fixed17Hard", math.Ldexp(8887055249355788, 665), 'e', 17, 64}, + {"64Fixed18Hard", math.Ldexp(6994187472632449, 690), 'e', 18, 64}, + + // Trigger slow path (see issue #15672). + // The shortest is: 8.034137530808823e+43 + {"Slowpath64", 8.03413753080882349e+43, 'e', -1, 64}, + // This denormal is pathological because the lower/upper + // halfways to neighboring floats are: + // 622666234635.321003e-320 ~= 622666234635.321e-320 + // 622666234635.321497e-320 ~= 622666234635.3215e-320 + // making it hard to find the 3rd digit + {"SlowpathDenormal64", 622666234635.3213e-320, 'e', -1, 64}, +} + +func BenchmarkFormatFloat(b *testing.B) { + for _, c := range ftoaBenches { + b.Run(c.name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + FormatFloat(c.float, c.fmt, c.prec, c.bitSize) + } + }) + } +} + +func BenchmarkAppendFloat(b *testing.B) { + dst := make([]byte, 30) + for _, c := range ftoaBenches { + b.Run(c.name, func(b *testing.B) { + for i := 0; i < b.N; i++ { + AppendFloat(dst[:0], c.float, c.fmt, c.prec, c.bitSize) + } + }) + } +} diff --git a/util/gnolanddev/strconv/ftoaryu.gno b/util/gnolanddev/strconv/ftoaryu.gno new file mode 100644 index 00000000..7b965621 --- /dev/null +++ b/util/gnolanddev/strconv/ftoaryu.gno @@ -0,0 +1,1280 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package strconv + +import ( + "math/bits" +) + +// binary to decimal conversion using the Ryū algorithm. +// +// See Ulf Adams, "Ryū: Fast Float-to-String Conversion" (doi:10.1145/3192366.3192369) +// +// Fixed precision formatting is a variant of the original paper's +// algorithm, where a single multiplication by 10^k is required, +// sharing the same rounding guarantees. + +// ryuFtoaFixed32 formats mant*(2^exp) with prec decimal digits. +func ryuFtoaFixed32(d *decimalSlice, mant uint32, exp int, prec int) { + if prec < 0 { + panic("ryuFtoaFixed32 called with negative prec") + } + if prec > 9 { + panic("ryuFtoaFixed32 called with prec > 9") + } + // Zero input. + if mant == 0 { + d.nd, d.dp = 0, 0 + return + } + // Renormalize to a 25-bit mantissa. + e2 := exp + if b := bits.Len32(mant); b < 25 { + mant <<= uint(25 - b) + e2 += b - 25 + } + // Choose an exponent such that rounded mant*(2^e2)*(10^q) has + // at least prec decimal digits, i.e + // mant*(2^e2)*(10^q) >= 10^(prec-1) + // Because mant >= 2^24, it is enough to choose: + // 2^(e2+24) >= 10^(-q+prec-1) + // or q = -mulByLog2Log10(e2+24) + prec - 1 + q := -mulByLog2Log10(e2+24) + prec - 1 + + // Now compute mant*(2^e2)*(10^q). + // Is it an exact computation? + // Only small positive powers of 10 are exact (5^28 has 66 bits). + exact := q <= 27 && q >= 0 + + di, dexp2, d0 := mult64bitPow10(mant, e2, q) + if dexp2 >= 0 { + panic("not enough significant bits after mult64bitPow10") + } + // As a special case, computation might still be exact, if exponent + // was negative and if it amounts to computing an exact division. + // In that case, we ignore all lower bits. + // Note that division by 10^11 cannot be exact as 5^11 has 26 bits. + if q < 0 && q >= -10 && divisibleByPower5(uint64(mant), -q) { + exact = true + d0 = true + } + // Remove extra lower bits and keep rounding info. + extra := uint(-dexp2) + var extraMask uint32 = 1<>extra, di&extraMask + roundUp := false + if exact { + // If we computed an exact product, d + 1/2 + // should round to d+1 if 'd' is odd. + roundUp = dfrac > 1<<(extra-1) || + (dfrac == 1<<(extra-1) && !d0) || + (dfrac == 1<<(extra-1) && d0 && di&1 == 1) + } else { + // otherwise, d+1/2 always rounds up because + // we truncated below. + roundUp = dfrac>>(extra-1) == 1 + } + if dfrac != 0 { + d0 = false + } + // Proceed to the requested number of digits + formatDecimal(d, uint64(di), !d0, roundUp, prec) + // Adjust exponent + d.dp -= q +} + +// ryuFtoaFixed64 formats mant*(2^exp) with prec decimal digits. +func ryuFtoaFixed64(d *decimalSlice, mant uint64, exp int, prec int) { + if prec > 18 { + panic("ryuFtoaFixed64 called with prec > 18") + } + // Zero input. + if mant == 0 { + d.nd, d.dp = 0, 0 + return + } + // Renormalize to a 55-bit mantissa. + e2 := exp + if b := bits.Len64(mant); b < 55 { + mant = mant << uint(55-b) + e2 += b - 55 + } + // Choose an exponent such that rounded mant*(2^e2)*(10^q) has + // at least prec decimal digits, i.e + // mant*(2^e2)*(10^q) >= 10^(prec-1) + // Because mant >= 2^54, it is enough to choose: + // 2^(e2+54) >= 10^(-q+prec-1) + // or q = -mulByLog2Log10(e2+54) + prec - 1 + // + // The minimal required exponent is -mulByLog2Log10(1025)+18 = -291 + // The maximal required exponent is mulByLog2Log10(1074)+18 = 342 + q := -mulByLog2Log10(e2+54) + prec - 1 + + // Now compute mant*(2^e2)*(10^q). + // Is it an exact computation? + // Only small positive powers of 10 are exact (5^55 has 128 bits). + exact := q <= 55 && q >= 0 + + di, dexp2, d0 := mult128bitPow10(mant, e2, q) + if dexp2 >= 0 { + panic("not enough significant bits after mult128bitPow10") + } + // As a special case, computation might still be exact, if exponent + // was negative and if it amounts to computing an exact division. + // In that case, we ignore all lower bits. + // Note that division by 10^23 cannot be exact as 5^23 has 54 bits. + if q < 0 && q >= -22 && divisibleByPower5(mant, -q) { + exact = true + d0 = true + } + // Remove extra lower bits and keep rounding info. + extra := uint(-dexp2) + var extraMask uint64 = 1<>extra, di&extraMask + roundUp := false + if exact { + // If we computed an exact product, d + 1/2 + // should round to d+1 if 'd' is odd. + roundUp = dfrac > 1<<(extra-1) || + (dfrac == 1<<(extra-1) && !d0) || + (dfrac == 1<<(extra-1) && d0 && di&1 == 1) + } else { + // otherwise, d+1/2 always rounds up because + // we truncated below. + roundUp = dfrac>>(extra-1) == 1 + } + if dfrac != 0 { + d0 = false + } + // Proceed to the requested number of digits + formatDecimal(d, di, !d0, roundUp, prec) + // Adjust exponent + d.dp -= q +} + +var uint64pow10 = [...]uint64{ + 1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, + 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, +} + +// formatDecimal fills d with at most prec decimal digits +// of mantissa m. The boolean trunc indicates whether m +// is truncated compared to the original number being formatted. +func formatDecimal(d *decimalSlice, m uint64, trunc bool, roundUp bool, prec int) { + max := uint64pow10[prec] + trimmed := 0 + for m >= max { + a, b := m/10, m%10 + m = a + trimmed++ + if b > 5 { + roundUp = true + } else if b < 5 { + roundUp = false + } else { // b == 5 + // round up if there are trailing digits, + // or if the new value of m is odd (round-to-even convention) + roundUp = trunc || m&1 == 1 + } + if b != 0 { + trunc = true + } + } + if roundUp { + m++ + } + if m >= max { + // Happens if di was originally 99999....xx + m /= 10 + trimmed++ + } + // render digits (similar to formatBits) + n := uint(prec) + d.nd = prec + v := m + for v >= 100 { + var v1, v2 uint64 + if v>>32 == 0 { + v1, v2 = uint64(uint32(v)/100), uint64(uint32(v)%100) + } else { + v1, v2 = v/100, v%100 + } + n -= 2 + d.d[n+1] = smallsString[2*v2+1] + d.d[n+0] = smallsString[2*v2+0] + v = v1 + } + if v > 0 { + n-- + d.d[n] = smallsString[2*v+1] + } + if v >= 10 { + n-- + d.d[n] = smallsString[2*v] + } + for d.d[d.nd-1] == '0' { + d.nd-- + trimmed++ + } + d.dp = d.nd + trimmed +} + +// ryuFtoaShortest formats mant*2^exp with prec decimal digits. +func ryuFtoaShortest(d *decimalSlice, mant uint64, exp int, flt *floatInfo) { + if mant == 0 { + d.nd, d.dp = 0, 0 + return + } + // If input is an exact integer with fewer bits than the mantissa, + // the previous and next integer are not admissible representations. + if exp <= 0 && bits.TrailingZeros64(mant) >= -exp { + mant >>= uint(-exp) + ryuDigits(d, mant, mant, mant, true, false) + return + } + ml, mc, mu, e2 := computeBounds(mant, exp, flt) + if e2 == 0 { + ryuDigits(d, ml, mc, mu, true, false) + return + } + // Find 10^q *larger* than 2^-e2 + q := mulByLog2Log10(-e2) + 1 + + // We are going to multiply by 10^q using 128-bit arithmetic. + // The exponent is the same for all 3 numbers. + var dl, dc, du uint64 + var dl0, dc0, du0 bool + if flt == &float32info { + var dl32, dc32, du32 uint32 + dl32, _, dl0 = mult64bitPow10(uint32(ml), e2, q) + dc32, _, dc0 = mult64bitPow10(uint32(mc), e2, q) + du32, e2, du0 = mult64bitPow10(uint32(mu), e2, q) + dl, dc, du = uint64(dl32), uint64(dc32), uint64(du32) + } else { + dl, _, dl0 = mult128bitPow10(ml, e2, q) + dc, _, dc0 = mult128bitPow10(mc, e2, q) + du, e2, du0 = mult128bitPow10(mu, e2, q) + } + if e2 >= 0 { + panic("not enough significant bits after mult128bitPow10") + } + // Is it an exact computation? + if q > 55 { + // Large positive powers of ten are not exact + dl0, dc0, du0 = false, false, false + } + if q < 0 && q >= -24 { + // Division by a power of ten may be exact. + // (note that 5^25 is a 59-bit number so division by 5^25 is never exact). + if divisibleByPower5(ml, -q) { + dl0 = true + } + if divisibleByPower5(mc, -q) { + dc0 = true + } + if divisibleByPower5(mu, -q) { + du0 = true + } + } + // Express the results (dl, dc, du)*2^e2 as integers. + // Extra bits must be removed and rounding hints computed. + extra := uint(-e2) + var extraMask uint64 = 1<>extra, dl&extraMask + dc, fracc := dc>>extra, dc&extraMask + du, fracu := du>>extra, du&extraMask + // Is it allowed to use 'du' as a result? + // It is always allowed when it is truncated, but also + // if it is exact and the original binary mantissa is even + // When disallowed, we can subtract 1. + uok := !du0 || fracu > 0 + if du0 && fracu == 0 { + uok = mant&1 == 0 + } + if !uok { + du-- + } + // Is 'dc' the correctly rounded base 10 mantissa? + // The correct rounding might be dc+1 + cup := false // don't round up. + if dc0 { + // If we computed an exact product, the half integer + // should round to next (even) integer if 'dc' is odd. + cup = fracc > 1<<(extra-1) || + (fracc == 1<<(extra-1) && dc&1 == 1) + } else { + // otherwise, the result is a lower truncation of the ideal + // result. + cup = fracc>>(extra-1) == 1 + } + // Is 'dl' an allowed representation? + // Only if it is an exact value, and if the original binary mantissa + // was even. + lok := dl0 && fracl == 0 && (mant&1 == 0) + if !lok { + dl++ + } + // We need to remember whether the trimmed digits of 'dc' are zero. + c0 := dc0 && fracc == 0 + // render digits + ryuDigits(d, dl, dc, du, c0, cup) + d.dp -= q +} + +// mulByLog2Log10 returns math.Floor(x * log(2)/log(10)) for an integer x in +// the range -1600 <= x && x <= +1600. +// +// The range restriction lets us work in faster integer arithmetic instead of +// slower floating point arithmetic. Correctness is verified by unit tests. +func mulByLog2Log10(x int) int { + // log(2)/log(10) ≈ 0.30102999566 ≈ 78913 / 2^18 + return (x * 78913) >> 18 +} + +// mulByLog10Log2 returns math.Floor(x * log(10)/log(2)) for an integer x in +// the range -500 <= x && x <= +500. +// +// The range restriction lets us work in faster integer arithmetic instead of +// slower floating point arithmetic. Correctness is verified by unit tests. +func mulByLog10Log2(x int) int { + // log(10)/log(2) ≈ 3.32192809489 ≈ 108853 / 2^15 + return (x * 108853) >> 15 +} + +// computeBounds returns a floating-point vector (l, c, u)×2^e2 +// where the mantissas are 55-bit (or 26-bit) integers, describing the interval +// represented by the input float64 or float32. +func computeBounds(mant uint64, exp int, flt *floatInfo) (lower, central, upper uint64, e2 int) { + if mant != 1< 5e8) || (clo == 5e8 && cup) + ryuDigits32(d, lhi, chi, uhi, c0, cup, 8) + d.dp += 9 + } else { + d.nd = 0 + // emit high part + n := uint(9) + for v := chi; v > 0; { + v1, v2 := v/10, v%10 + v = v1 + n-- + d.d[n] = byte(v2 + '0') + } + d.d = d.d[n:] + d.nd = int(9 - n) + // emit low part + ryuDigits32(d, llo, clo, ulo, + c0, cup, d.nd+8) + } + // trim trailing zeros + for d.nd > 0 && d.d[d.nd-1] == '0' { + d.nd-- + } + // trim initial zeros + for d.nd > 0 && d.d[0] == '0' { + d.nd-- + d.dp-- + d.d = d.d[1:] + } +} + +// ryuDigits32 emits decimal digits for a number less than 1e9. +func ryuDigits32(d *decimalSlice, lower, central, upper uint32, + c0, cup bool, endindex int) { + if upper == 0 { + d.dp = endindex + 1 + return + } + trimmed := 0 + // Remember last trimmed digit to check for round-up. + // c0 will be used to remember zeroness of following digits. + cNextDigit := 0 + for upper > 0 { + // Repeatedly compute: + // l = Ceil(lower / 10^k) + // c = Round(central / 10^k) + // u = Floor(upper / 10^k) + // and stop when c goes out of the (l, u) interval. + l := (lower + 9) / 10 + c, cdigit := central/10, central%10 + u := upper / 10 + if l > u { + // don't trim the last digit as it is forbidden to go below l + // other, trim and exit now. + break + } + // Check that we didn't cross the lower boundary. + // The case where l < u but c == l-1 is essentially impossible, + // but may happen if: + // lower = ..11 + // central = ..19 + // upper = ..31 + // and means that 'central' is very close but less than + // an integer ending with many zeros, and usually + // the "round-up" logic hides the problem. + if l == c+1 && c < u { + c++ + cdigit = 0 + cup = false + } + trimmed++ + // Remember trimmed digits of c + c0 = c0 && cNextDigit == 0 + cNextDigit = int(cdigit) + lower, central, upper = l, c, u + } + // should we round up? + if trimmed > 0 { + cup = cNextDigit > 5 || + (cNextDigit == 5 && !c0) || + (cNextDigit == 5 && c0 && central&1 == 1) + } + if central < upper && cup { + central++ + } + // We know where the number ends, fill directly + endindex -= trimmed + v := central + n := endindex + for n > d.nd { + v1, v2 := v/100, v%100 + d.d[n] = smallsString[2*v2+1] + d.d[n-1] = smallsString[2*v2+0] + n -= 2 + v = v1 + } + if n == d.nd { + d.d[n] = byte(v + '0') + } + d.nd = endindex + 1 + d.dp = d.nd + trimmed +} + +// mult64bitPow10 takes a floating-point input with a 25-bit +// mantissa and multiplies it with 10^q. The resulting mantissa +// is m*P >> 57 where P is a 64-bit element of the detailedPowersOfTen tables. +// It is typically 31 or 32-bit wide. +// The returned boolean is true if all trimmed bits were zero. +// +// That is: +// +// m*2^e2 * round(10^q) = resM * 2^resE + ε +// exact = ε == 0 +func mult64bitPow10(m uint32, e2, q int) (resM uint32, resE int, exact bool) { + if q == 0 { + // P == 1<<63 + return m << 6, e2 - 6, true + } + if q < detailedPowersOfTenMinExp10 || detailedPowersOfTenMaxExp10 < q { + // This never happens due to the range of float32/float64 exponent + panic("mult64bitPow10: power of 10 is out of range") + } + pow := detailedPowersOfTen[q-detailedPowersOfTenMinExp10][1] + if q < 0 { + // Inverse powers of ten must be rounded up. + pow += 1 + } + hi, lo := bits.Mul64(uint64(m), pow) + e2 += mulByLog10Log2(q) - 63 + 57 + return uint32(hi<<7 | lo>>57), e2, lo<<7 == 0 +} + +// mult128bitPow10 takes a floating-point input with a 55-bit +// mantissa and multiplies it with 10^q. The resulting mantissa +// is m*P >> 119 where P is a 128-bit element of the detailedPowersOfTen tables. +// It is typically 63 or 64-bit wide. +// The returned boolean is true is all trimmed bits were zero. +// +// That is: +// +// m*2^e2 * round(10^q) = resM * 2^resE + ε +// exact = ε == 0 +func mult128bitPow10(m uint64, e2, q int) (resM uint64, resE int, exact bool) { + if q == 0 { + // P == 1<<127 + return m << 8, e2 - 8, true + } + if q < detailedPowersOfTenMinExp10 || detailedPowersOfTenMaxExp10 < q { + // This never happens due to the range of float32/float64 exponent + panic("mult128bitPow10: power of 10 is out of range") + } + pow := detailedPowersOfTen[q-detailedPowersOfTenMinExp10] + if q < 0 { + // Inverse powers of ten must be rounded up. + pow[0] += 1 + } + e2 += mulByLog10Log2(q) - 127 + 119 + + // long multiplication + l1, l0 := bits.Mul64(m, pow[0]) + h1, h0 := bits.Mul64(m, pow[1]) + mid, carry := bits.Add64(l1, h0, 0) + h1 += carry + return h1<<9 | mid>>55, e2, mid<<9 == 0 && l0 == 0 +} + +func divisibleByPower5(m uint64, k int) bool { + if m == 0 { + return true + } + for i := 0; i < k; i++ { + if m%5 != 0 { + return false + } + m /= 5 + } + return true +} + +// divmod1e9 computes quotient and remainder of division by 1e9, +// avoiding runtime uint64 division on 32-bit platforms. +func divmod1e9(x uint64) (uint32, uint32) { + return uint32(x / 1e9), uint32(x % 1e9) +} + +// detailedPowersOfTen{Min,Max}Exp10 is the power of 10 represented by the +// first and last rows of detailedPowersOfTen. Both bounds are inclusive. +const ( + detailedPowersOfTenMinExp10 = -348 + detailedPowersOfTenMaxExp10 = +347 +) + +// detailedPowersOfTen contains 128-bit mantissa approximations (rounded down) +// to the powers of 10. For example: +// +// - 1e43 ≈ (0xE596B7B0_C643C719 * (2 ** 79)) +// - 1e43 = (0xE596B7B0_C643C719_6D9CCD05_D0000000 * (2 ** 15)) +// +// The mantissas are explicitly listed. The exponents are implied by a linear +// expression with slope 217706.0/65536.0 ≈ log(10)/log(2). +// +// The table was generated by +// https://github.com/google/wuffs/blob/ba3818cb6b473a2ed0b38ecfc07dbbd3a97e8ae7/script/print-mpb-powers-of-10.go +var detailedPowersOfTen = [...][2]uint64{ + {0x1732C869CD60E453, 0xFA8FD5A0081C0288}, // 1e-348 + {0x0E7FBD42205C8EB4, 0x9C99E58405118195}, // 1e-347 + {0x521FAC92A873B261, 0xC3C05EE50655E1FA}, // 1e-346 + {0xE6A797B752909EF9, 0xF4B0769E47EB5A78}, // 1e-345 + {0x9028BED2939A635C, 0x98EE4A22ECF3188B}, // 1e-344 + {0x7432EE873880FC33, 0xBF29DCABA82FDEAE}, // 1e-343 + {0x113FAA2906A13B3F, 0xEEF453D6923BD65A}, // 1e-342 + {0x4AC7CA59A424C507, 0x9558B4661B6565F8}, // 1e-341 + {0x5D79BCF00D2DF649, 0xBAAEE17FA23EBF76}, // 1e-340 + {0xF4D82C2C107973DC, 0xE95A99DF8ACE6F53}, // 1e-339 + {0x79071B9B8A4BE869, 0x91D8A02BB6C10594}, // 1e-338 + {0x9748E2826CDEE284, 0xB64EC836A47146F9}, // 1e-337 + {0xFD1B1B2308169B25, 0xE3E27A444D8D98B7}, // 1e-336 + {0xFE30F0F5E50E20F7, 0x8E6D8C6AB0787F72}, // 1e-335 + {0xBDBD2D335E51A935, 0xB208EF855C969F4F}, // 1e-334 + {0xAD2C788035E61382, 0xDE8B2B66B3BC4723}, // 1e-333 + {0x4C3BCB5021AFCC31, 0x8B16FB203055AC76}, // 1e-332 + {0xDF4ABE242A1BBF3D, 0xADDCB9E83C6B1793}, // 1e-331 + {0xD71D6DAD34A2AF0D, 0xD953E8624B85DD78}, // 1e-330 + {0x8672648C40E5AD68, 0x87D4713D6F33AA6B}, // 1e-329 + {0x680EFDAF511F18C2, 0xA9C98D8CCB009506}, // 1e-328 + {0x0212BD1B2566DEF2, 0xD43BF0EFFDC0BA48}, // 1e-327 + {0x014BB630F7604B57, 0x84A57695FE98746D}, // 1e-326 + {0x419EA3BD35385E2D, 0xA5CED43B7E3E9188}, // 1e-325 + {0x52064CAC828675B9, 0xCF42894A5DCE35EA}, // 1e-324 + {0x7343EFEBD1940993, 0x818995CE7AA0E1B2}, // 1e-323 + {0x1014EBE6C5F90BF8, 0xA1EBFB4219491A1F}, // 1e-322 + {0xD41A26E077774EF6, 0xCA66FA129F9B60A6}, // 1e-321 + {0x8920B098955522B4, 0xFD00B897478238D0}, // 1e-320 + {0x55B46E5F5D5535B0, 0x9E20735E8CB16382}, // 1e-319 + {0xEB2189F734AA831D, 0xC5A890362FDDBC62}, // 1e-318 + {0xA5E9EC7501D523E4, 0xF712B443BBD52B7B}, // 1e-317 + {0x47B233C92125366E, 0x9A6BB0AA55653B2D}, // 1e-316 + {0x999EC0BB696E840A, 0xC1069CD4EABE89F8}, // 1e-315 + {0xC00670EA43CA250D, 0xF148440A256E2C76}, // 1e-314 + {0x380406926A5E5728, 0x96CD2A865764DBCA}, // 1e-313 + {0xC605083704F5ECF2, 0xBC807527ED3E12BC}, // 1e-312 + {0xF7864A44C633682E, 0xEBA09271E88D976B}, // 1e-311 + {0x7AB3EE6AFBE0211D, 0x93445B8731587EA3}, // 1e-310 + {0x5960EA05BAD82964, 0xB8157268FDAE9E4C}, // 1e-309 + {0x6FB92487298E33BD, 0xE61ACF033D1A45DF}, // 1e-308 + {0xA5D3B6D479F8E056, 0x8FD0C16206306BAB}, // 1e-307 + {0x8F48A4899877186C, 0xB3C4F1BA87BC8696}, // 1e-306 + {0x331ACDABFE94DE87, 0xE0B62E2929ABA83C}, // 1e-305 + {0x9FF0C08B7F1D0B14, 0x8C71DCD9BA0B4925}, // 1e-304 + {0x07ECF0AE5EE44DD9, 0xAF8E5410288E1B6F}, // 1e-303 + {0xC9E82CD9F69D6150, 0xDB71E91432B1A24A}, // 1e-302 + {0xBE311C083A225CD2, 0x892731AC9FAF056E}, // 1e-301 + {0x6DBD630A48AAF406, 0xAB70FE17C79AC6CA}, // 1e-300 + {0x092CBBCCDAD5B108, 0xD64D3D9DB981787D}, // 1e-299 + {0x25BBF56008C58EA5, 0x85F0468293F0EB4E}, // 1e-298 + {0xAF2AF2B80AF6F24E, 0xA76C582338ED2621}, // 1e-297 + {0x1AF5AF660DB4AEE1, 0xD1476E2C07286FAA}, // 1e-296 + {0x50D98D9FC890ED4D, 0x82CCA4DB847945CA}, // 1e-295 + {0xE50FF107BAB528A0, 0xA37FCE126597973C}, // 1e-294 + {0x1E53ED49A96272C8, 0xCC5FC196FEFD7D0C}, // 1e-293 + {0x25E8E89C13BB0F7A, 0xFF77B1FCBEBCDC4F}, // 1e-292 + {0x77B191618C54E9AC, 0x9FAACF3DF73609B1}, // 1e-291 + {0xD59DF5B9EF6A2417, 0xC795830D75038C1D}, // 1e-290 + {0x4B0573286B44AD1D, 0xF97AE3D0D2446F25}, // 1e-289 + {0x4EE367F9430AEC32, 0x9BECCE62836AC577}, // 1e-288 + {0x229C41F793CDA73F, 0xC2E801FB244576D5}, // 1e-287 + {0x6B43527578C1110F, 0xF3A20279ED56D48A}, // 1e-286 + {0x830A13896B78AAA9, 0x9845418C345644D6}, // 1e-285 + {0x23CC986BC656D553, 0xBE5691EF416BD60C}, // 1e-284 + {0x2CBFBE86B7EC8AA8, 0xEDEC366B11C6CB8F}, // 1e-283 + {0x7BF7D71432F3D6A9, 0x94B3A202EB1C3F39}, // 1e-282 + {0xDAF5CCD93FB0CC53, 0xB9E08A83A5E34F07}, // 1e-281 + {0xD1B3400F8F9CFF68, 0xE858AD248F5C22C9}, // 1e-280 + {0x23100809B9C21FA1, 0x91376C36D99995BE}, // 1e-279 + {0xABD40A0C2832A78A, 0xB58547448FFFFB2D}, // 1e-278 + {0x16C90C8F323F516C, 0xE2E69915B3FFF9F9}, // 1e-277 + {0xAE3DA7D97F6792E3, 0x8DD01FAD907FFC3B}, // 1e-276 + {0x99CD11CFDF41779C, 0xB1442798F49FFB4A}, // 1e-275 + {0x40405643D711D583, 0xDD95317F31C7FA1D}, // 1e-274 + {0x482835EA666B2572, 0x8A7D3EEF7F1CFC52}, // 1e-273 + {0xDA3243650005EECF, 0xAD1C8EAB5EE43B66}, // 1e-272 + {0x90BED43E40076A82, 0xD863B256369D4A40}, // 1e-271 + {0x5A7744A6E804A291, 0x873E4F75E2224E68}, // 1e-270 + {0x711515D0A205CB36, 0xA90DE3535AAAE202}, // 1e-269 + {0x0D5A5B44CA873E03, 0xD3515C2831559A83}, // 1e-268 + {0xE858790AFE9486C2, 0x8412D9991ED58091}, // 1e-267 + {0x626E974DBE39A872, 0xA5178FFF668AE0B6}, // 1e-266 + {0xFB0A3D212DC8128F, 0xCE5D73FF402D98E3}, // 1e-265 + {0x7CE66634BC9D0B99, 0x80FA687F881C7F8E}, // 1e-264 + {0x1C1FFFC1EBC44E80, 0xA139029F6A239F72}, // 1e-263 + {0xA327FFB266B56220, 0xC987434744AC874E}, // 1e-262 + {0x4BF1FF9F0062BAA8, 0xFBE9141915D7A922}, // 1e-261 + {0x6F773FC3603DB4A9, 0x9D71AC8FADA6C9B5}, // 1e-260 + {0xCB550FB4384D21D3, 0xC4CE17B399107C22}, // 1e-259 + {0x7E2A53A146606A48, 0xF6019DA07F549B2B}, // 1e-258 + {0x2EDA7444CBFC426D, 0x99C102844F94E0FB}, // 1e-257 + {0xFA911155FEFB5308, 0xC0314325637A1939}, // 1e-256 + {0x793555AB7EBA27CA, 0xF03D93EEBC589F88}, // 1e-255 + {0x4BC1558B2F3458DE, 0x96267C7535B763B5}, // 1e-254 + {0x9EB1AAEDFB016F16, 0xBBB01B9283253CA2}, // 1e-253 + {0x465E15A979C1CADC, 0xEA9C227723EE8BCB}, // 1e-252 + {0x0BFACD89EC191EC9, 0x92A1958A7675175F}, // 1e-251 + {0xCEF980EC671F667B, 0xB749FAED14125D36}, // 1e-250 + {0x82B7E12780E7401A, 0xE51C79A85916F484}, // 1e-249 + {0xD1B2ECB8B0908810, 0x8F31CC0937AE58D2}, // 1e-248 + {0x861FA7E6DCB4AA15, 0xB2FE3F0B8599EF07}, // 1e-247 + {0x67A791E093E1D49A, 0xDFBDCECE67006AC9}, // 1e-246 + {0xE0C8BB2C5C6D24E0, 0x8BD6A141006042BD}, // 1e-245 + {0x58FAE9F773886E18, 0xAECC49914078536D}, // 1e-244 + {0xAF39A475506A899E, 0xDA7F5BF590966848}, // 1e-243 + {0x6D8406C952429603, 0x888F99797A5E012D}, // 1e-242 + {0xC8E5087BA6D33B83, 0xAAB37FD7D8F58178}, // 1e-241 + {0xFB1E4A9A90880A64, 0xD5605FCDCF32E1D6}, // 1e-240 + {0x5CF2EEA09A55067F, 0x855C3BE0A17FCD26}, // 1e-239 + {0xF42FAA48C0EA481E, 0xA6B34AD8C9DFC06F}, // 1e-238 + {0xF13B94DAF124DA26, 0xD0601D8EFC57B08B}, // 1e-237 + {0x76C53D08D6B70858, 0x823C12795DB6CE57}, // 1e-236 + {0x54768C4B0C64CA6E, 0xA2CB1717B52481ED}, // 1e-235 + {0xA9942F5DCF7DFD09, 0xCB7DDCDDA26DA268}, // 1e-234 + {0xD3F93B35435D7C4C, 0xFE5D54150B090B02}, // 1e-233 + {0xC47BC5014A1A6DAF, 0x9EFA548D26E5A6E1}, // 1e-232 + {0x359AB6419CA1091B, 0xC6B8E9B0709F109A}, // 1e-231 + {0xC30163D203C94B62, 0xF867241C8CC6D4C0}, // 1e-230 + {0x79E0DE63425DCF1D, 0x9B407691D7FC44F8}, // 1e-229 + {0x985915FC12F542E4, 0xC21094364DFB5636}, // 1e-228 + {0x3E6F5B7B17B2939D, 0xF294B943E17A2BC4}, // 1e-227 + {0xA705992CEECF9C42, 0x979CF3CA6CEC5B5A}, // 1e-226 + {0x50C6FF782A838353, 0xBD8430BD08277231}, // 1e-225 + {0xA4F8BF5635246428, 0xECE53CEC4A314EBD}, // 1e-224 + {0x871B7795E136BE99, 0x940F4613AE5ED136}, // 1e-223 + {0x28E2557B59846E3F, 0xB913179899F68584}, // 1e-222 + {0x331AEADA2FE589CF, 0xE757DD7EC07426E5}, // 1e-221 + {0x3FF0D2C85DEF7621, 0x9096EA6F3848984F}, // 1e-220 + {0x0FED077A756B53A9, 0xB4BCA50B065ABE63}, // 1e-219 + {0xD3E8495912C62894, 0xE1EBCE4DC7F16DFB}, // 1e-218 + {0x64712DD7ABBBD95C, 0x8D3360F09CF6E4BD}, // 1e-217 + {0xBD8D794D96AACFB3, 0xB080392CC4349DEC}, // 1e-216 + {0xECF0D7A0FC5583A0, 0xDCA04777F541C567}, // 1e-215 + {0xF41686C49DB57244, 0x89E42CAAF9491B60}, // 1e-214 + {0x311C2875C522CED5, 0xAC5D37D5B79B6239}, // 1e-213 + {0x7D633293366B828B, 0xD77485CB25823AC7}, // 1e-212 + {0xAE5DFF9C02033197, 0x86A8D39EF77164BC}, // 1e-211 + {0xD9F57F830283FDFC, 0xA8530886B54DBDEB}, // 1e-210 + {0xD072DF63C324FD7B, 0xD267CAA862A12D66}, // 1e-209 + {0x4247CB9E59F71E6D, 0x8380DEA93DA4BC60}, // 1e-208 + {0x52D9BE85F074E608, 0xA46116538D0DEB78}, // 1e-207 + {0x67902E276C921F8B, 0xCD795BE870516656}, // 1e-206 + {0x00BA1CD8A3DB53B6, 0x806BD9714632DFF6}, // 1e-205 + {0x80E8A40ECCD228A4, 0xA086CFCD97BF97F3}, // 1e-204 + {0x6122CD128006B2CD, 0xC8A883C0FDAF7DF0}, // 1e-203 + {0x796B805720085F81, 0xFAD2A4B13D1B5D6C}, // 1e-202 + {0xCBE3303674053BB0, 0x9CC3A6EEC6311A63}, // 1e-201 + {0xBEDBFC4411068A9C, 0xC3F490AA77BD60FC}, // 1e-200 + {0xEE92FB5515482D44, 0xF4F1B4D515ACB93B}, // 1e-199 + {0x751BDD152D4D1C4A, 0x991711052D8BF3C5}, // 1e-198 + {0xD262D45A78A0635D, 0xBF5CD54678EEF0B6}, // 1e-197 + {0x86FB897116C87C34, 0xEF340A98172AACE4}, // 1e-196 + {0xD45D35E6AE3D4DA0, 0x9580869F0E7AAC0E}, // 1e-195 + {0x8974836059CCA109, 0xBAE0A846D2195712}, // 1e-194 + {0x2BD1A438703FC94B, 0xE998D258869FACD7}, // 1e-193 + {0x7B6306A34627DDCF, 0x91FF83775423CC06}, // 1e-192 + {0x1A3BC84C17B1D542, 0xB67F6455292CBF08}, // 1e-191 + {0x20CABA5F1D9E4A93, 0xE41F3D6A7377EECA}, // 1e-190 + {0x547EB47B7282EE9C, 0x8E938662882AF53E}, // 1e-189 + {0xE99E619A4F23AA43, 0xB23867FB2A35B28D}, // 1e-188 + {0x6405FA00E2EC94D4, 0xDEC681F9F4C31F31}, // 1e-187 + {0xDE83BC408DD3DD04, 0x8B3C113C38F9F37E}, // 1e-186 + {0x9624AB50B148D445, 0xAE0B158B4738705E}, // 1e-185 + {0x3BADD624DD9B0957, 0xD98DDAEE19068C76}, // 1e-184 + {0xE54CA5D70A80E5D6, 0x87F8A8D4CFA417C9}, // 1e-183 + {0x5E9FCF4CCD211F4C, 0xA9F6D30A038D1DBC}, // 1e-182 + {0x7647C3200069671F, 0xD47487CC8470652B}, // 1e-181 + {0x29ECD9F40041E073, 0x84C8D4DFD2C63F3B}, // 1e-180 + {0xF468107100525890, 0xA5FB0A17C777CF09}, // 1e-179 + {0x7182148D4066EEB4, 0xCF79CC9DB955C2CC}, // 1e-178 + {0xC6F14CD848405530, 0x81AC1FE293D599BF}, // 1e-177 + {0xB8ADA00E5A506A7C, 0xA21727DB38CB002F}, // 1e-176 + {0xA6D90811F0E4851C, 0xCA9CF1D206FDC03B}, // 1e-175 + {0x908F4A166D1DA663, 0xFD442E4688BD304A}, // 1e-174 + {0x9A598E4E043287FE, 0x9E4A9CEC15763E2E}, // 1e-173 + {0x40EFF1E1853F29FD, 0xC5DD44271AD3CDBA}, // 1e-172 + {0xD12BEE59E68EF47C, 0xF7549530E188C128}, // 1e-171 + {0x82BB74F8301958CE, 0x9A94DD3E8CF578B9}, // 1e-170 + {0xE36A52363C1FAF01, 0xC13A148E3032D6E7}, // 1e-169 + {0xDC44E6C3CB279AC1, 0xF18899B1BC3F8CA1}, // 1e-168 + {0x29AB103A5EF8C0B9, 0x96F5600F15A7B7E5}, // 1e-167 + {0x7415D448F6B6F0E7, 0xBCB2B812DB11A5DE}, // 1e-166 + {0x111B495B3464AD21, 0xEBDF661791D60F56}, // 1e-165 + {0xCAB10DD900BEEC34, 0x936B9FCEBB25C995}, // 1e-164 + {0x3D5D514F40EEA742, 0xB84687C269EF3BFB}, // 1e-163 + {0x0CB4A5A3112A5112, 0xE65829B3046B0AFA}, // 1e-162 + {0x47F0E785EABA72AB, 0x8FF71A0FE2C2E6DC}, // 1e-161 + {0x59ED216765690F56, 0xB3F4E093DB73A093}, // 1e-160 + {0x306869C13EC3532C, 0xE0F218B8D25088B8}, // 1e-159 + {0x1E414218C73A13FB, 0x8C974F7383725573}, // 1e-158 + {0xE5D1929EF90898FA, 0xAFBD2350644EEACF}, // 1e-157 + {0xDF45F746B74ABF39, 0xDBAC6C247D62A583}, // 1e-156 + {0x6B8BBA8C328EB783, 0x894BC396CE5DA772}, // 1e-155 + {0x066EA92F3F326564, 0xAB9EB47C81F5114F}, // 1e-154 + {0xC80A537B0EFEFEBD, 0xD686619BA27255A2}, // 1e-153 + {0xBD06742CE95F5F36, 0x8613FD0145877585}, // 1e-152 + {0x2C48113823B73704, 0xA798FC4196E952E7}, // 1e-151 + {0xF75A15862CA504C5, 0xD17F3B51FCA3A7A0}, // 1e-150 + {0x9A984D73DBE722FB, 0x82EF85133DE648C4}, // 1e-149 + {0xC13E60D0D2E0EBBA, 0xA3AB66580D5FDAF5}, // 1e-148 + {0x318DF905079926A8, 0xCC963FEE10B7D1B3}, // 1e-147 + {0xFDF17746497F7052, 0xFFBBCFE994E5C61F}, // 1e-146 + {0xFEB6EA8BEDEFA633, 0x9FD561F1FD0F9BD3}, // 1e-145 + {0xFE64A52EE96B8FC0, 0xC7CABA6E7C5382C8}, // 1e-144 + {0x3DFDCE7AA3C673B0, 0xF9BD690A1B68637B}, // 1e-143 + {0x06BEA10CA65C084E, 0x9C1661A651213E2D}, // 1e-142 + {0x486E494FCFF30A62, 0xC31BFA0FE5698DB8}, // 1e-141 + {0x5A89DBA3C3EFCCFA, 0xF3E2F893DEC3F126}, // 1e-140 + {0xF89629465A75E01C, 0x986DDB5C6B3A76B7}, // 1e-139 + {0xF6BBB397F1135823, 0xBE89523386091465}, // 1e-138 + {0x746AA07DED582E2C, 0xEE2BA6C0678B597F}, // 1e-137 + {0xA8C2A44EB4571CDC, 0x94DB483840B717EF}, // 1e-136 + {0x92F34D62616CE413, 0xBA121A4650E4DDEB}, // 1e-135 + {0x77B020BAF9C81D17, 0xE896A0D7E51E1566}, // 1e-134 + {0x0ACE1474DC1D122E, 0x915E2486EF32CD60}, // 1e-133 + {0x0D819992132456BA, 0xB5B5ADA8AAFF80B8}, // 1e-132 + {0x10E1FFF697ED6C69, 0xE3231912D5BF60E6}, // 1e-131 + {0xCA8D3FFA1EF463C1, 0x8DF5EFABC5979C8F}, // 1e-130 + {0xBD308FF8A6B17CB2, 0xB1736B96B6FD83B3}, // 1e-129 + {0xAC7CB3F6D05DDBDE, 0xDDD0467C64BCE4A0}, // 1e-128 + {0x6BCDF07A423AA96B, 0x8AA22C0DBEF60EE4}, // 1e-127 + {0x86C16C98D2C953C6, 0xAD4AB7112EB3929D}, // 1e-126 + {0xE871C7BF077BA8B7, 0xD89D64D57A607744}, // 1e-125 + {0x11471CD764AD4972, 0x87625F056C7C4A8B}, // 1e-124 + {0xD598E40D3DD89BCF, 0xA93AF6C6C79B5D2D}, // 1e-123 + {0x4AFF1D108D4EC2C3, 0xD389B47879823479}, // 1e-122 + {0xCEDF722A585139BA, 0x843610CB4BF160CB}, // 1e-121 + {0xC2974EB4EE658828, 0xA54394FE1EEDB8FE}, // 1e-120 + {0x733D226229FEEA32, 0xCE947A3DA6A9273E}, // 1e-119 + {0x0806357D5A3F525F, 0x811CCC668829B887}, // 1e-118 + {0xCA07C2DCB0CF26F7, 0xA163FF802A3426A8}, // 1e-117 + {0xFC89B393DD02F0B5, 0xC9BCFF6034C13052}, // 1e-116 + {0xBBAC2078D443ACE2, 0xFC2C3F3841F17C67}, // 1e-115 + {0xD54B944B84AA4C0D, 0x9D9BA7832936EDC0}, // 1e-114 + {0x0A9E795E65D4DF11, 0xC5029163F384A931}, // 1e-113 + {0x4D4617B5FF4A16D5, 0xF64335BCF065D37D}, // 1e-112 + {0x504BCED1BF8E4E45, 0x99EA0196163FA42E}, // 1e-111 + {0xE45EC2862F71E1D6, 0xC06481FB9BCF8D39}, // 1e-110 + {0x5D767327BB4E5A4C, 0xF07DA27A82C37088}, // 1e-109 + {0x3A6A07F8D510F86F, 0x964E858C91BA2655}, // 1e-108 + {0x890489F70A55368B, 0xBBE226EFB628AFEA}, // 1e-107 + {0x2B45AC74CCEA842E, 0xEADAB0ABA3B2DBE5}, // 1e-106 + {0x3B0B8BC90012929D, 0x92C8AE6B464FC96F}, // 1e-105 + {0x09CE6EBB40173744, 0xB77ADA0617E3BBCB}, // 1e-104 + {0xCC420A6A101D0515, 0xE55990879DDCAABD}, // 1e-103 + {0x9FA946824A12232D, 0x8F57FA54C2A9EAB6}, // 1e-102 + {0x47939822DC96ABF9, 0xB32DF8E9F3546564}, // 1e-101 + {0x59787E2B93BC56F7, 0xDFF9772470297EBD}, // 1e-100 + {0x57EB4EDB3C55B65A, 0x8BFBEA76C619EF36}, // 1e-99 + {0xEDE622920B6B23F1, 0xAEFAE51477A06B03}, // 1e-98 + {0xE95FAB368E45ECED, 0xDAB99E59958885C4}, // 1e-97 + {0x11DBCB0218EBB414, 0x88B402F7FD75539B}, // 1e-96 + {0xD652BDC29F26A119, 0xAAE103B5FCD2A881}, // 1e-95 + {0x4BE76D3346F0495F, 0xD59944A37C0752A2}, // 1e-94 + {0x6F70A4400C562DDB, 0x857FCAE62D8493A5}, // 1e-93 + {0xCB4CCD500F6BB952, 0xA6DFBD9FB8E5B88E}, // 1e-92 + {0x7E2000A41346A7A7, 0xD097AD07A71F26B2}, // 1e-91 + {0x8ED400668C0C28C8, 0x825ECC24C873782F}, // 1e-90 + {0x728900802F0F32FA, 0xA2F67F2DFA90563B}, // 1e-89 + {0x4F2B40A03AD2FFB9, 0xCBB41EF979346BCA}, // 1e-88 + {0xE2F610C84987BFA8, 0xFEA126B7D78186BC}, // 1e-87 + {0x0DD9CA7D2DF4D7C9, 0x9F24B832E6B0F436}, // 1e-86 + {0x91503D1C79720DBB, 0xC6EDE63FA05D3143}, // 1e-85 + {0x75A44C6397CE912A, 0xF8A95FCF88747D94}, // 1e-84 + {0xC986AFBE3EE11ABA, 0x9B69DBE1B548CE7C}, // 1e-83 + {0xFBE85BADCE996168, 0xC24452DA229B021B}, // 1e-82 + {0xFAE27299423FB9C3, 0xF2D56790AB41C2A2}, // 1e-81 + {0xDCCD879FC967D41A, 0x97C560BA6B0919A5}, // 1e-80 + {0x5400E987BBC1C920, 0xBDB6B8E905CB600F}, // 1e-79 + {0x290123E9AAB23B68, 0xED246723473E3813}, // 1e-78 + {0xF9A0B6720AAF6521, 0x9436C0760C86E30B}, // 1e-77 + {0xF808E40E8D5B3E69, 0xB94470938FA89BCE}, // 1e-76 + {0xB60B1D1230B20E04, 0xE7958CB87392C2C2}, // 1e-75 + {0xB1C6F22B5E6F48C2, 0x90BD77F3483BB9B9}, // 1e-74 + {0x1E38AEB6360B1AF3, 0xB4ECD5F01A4AA828}, // 1e-73 + {0x25C6DA63C38DE1B0, 0xE2280B6C20DD5232}, // 1e-72 + {0x579C487E5A38AD0E, 0x8D590723948A535F}, // 1e-71 + {0x2D835A9DF0C6D851, 0xB0AF48EC79ACE837}, // 1e-70 + {0xF8E431456CF88E65, 0xDCDB1B2798182244}, // 1e-69 + {0x1B8E9ECB641B58FF, 0x8A08F0F8BF0F156B}, // 1e-68 + {0xE272467E3D222F3F, 0xAC8B2D36EED2DAC5}, // 1e-67 + {0x5B0ED81DCC6ABB0F, 0xD7ADF884AA879177}, // 1e-66 + {0x98E947129FC2B4E9, 0x86CCBB52EA94BAEA}, // 1e-65 + {0x3F2398D747B36224, 0xA87FEA27A539E9A5}, // 1e-64 + {0x8EEC7F0D19A03AAD, 0xD29FE4B18E88640E}, // 1e-63 + {0x1953CF68300424AC, 0x83A3EEEEF9153E89}, // 1e-62 + {0x5FA8C3423C052DD7, 0xA48CEAAAB75A8E2B}, // 1e-61 + {0x3792F412CB06794D, 0xCDB02555653131B6}, // 1e-60 + {0xE2BBD88BBEE40BD0, 0x808E17555F3EBF11}, // 1e-59 + {0x5B6ACEAEAE9D0EC4, 0xA0B19D2AB70E6ED6}, // 1e-58 + {0xF245825A5A445275, 0xC8DE047564D20A8B}, // 1e-57 + {0xEED6E2F0F0D56712, 0xFB158592BE068D2E}, // 1e-56 + {0x55464DD69685606B, 0x9CED737BB6C4183D}, // 1e-55 + {0xAA97E14C3C26B886, 0xC428D05AA4751E4C}, // 1e-54 + {0xD53DD99F4B3066A8, 0xF53304714D9265DF}, // 1e-53 + {0xE546A8038EFE4029, 0x993FE2C6D07B7FAB}, // 1e-52 + {0xDE98520472BDD033, 0xBF8FDB78849A5F96}, // 1e-51 + {0x963E66858F6D4440, 0xEF73D256A5C0F77C}, // 1e-50 + {0xDDE7001379A44AA8, 0x95A8637627989AAD}, // 1e-49 + {0x5560C018580D5D52, 0xBB127C53B17EC159}, // 1e-48 + {0xAAB8F01E6E10B4A6, 0xE9D71B689DDE71AF}, // 1e-47 + {0xCAB3961304CA70E8, 0x9226712162AB070D}, // 1e-46 + {0x3D607B97C5FD0D22, 0xB6B00D69BB55C8D1}, // 1e-45 + {0x8CB89A7DB77C506A, 0xE45C10C42A2B3B05}, // 1e-44 + {0x77F3608E92ADB242, 0x8EB98A7A9A5B04E3}, // 1e-43 + {0x55F038B237591ED3, 0xB267ED1940F1C61C}, // 1e-42 + {0x6B6C46DEC52F6688, 0xDF01E85F912E37A3}, // 1e-41 + {0x2323AC4B3B3DA015, 0x8B61313BBABCE2C6}, // 1e-40 + {0xABEC975E0A0D081A, 0xAE397D8AA96C1B77}, // 1e-39 + {0x96E7BD358C904A21, 0xD9C7DCED53C72255}, // 1e-38 + {0x7E50D64177DA2E54, 0x881CEA14545C7575}, // 1e-37 + {0xDDE50BD1D5D0B9E9, 0xAA242499697392D2}, // 1e-36 + {0x955E4EC64B44E864, 0xD4AD2DBFC3D07787}, // 1e-35 + {0xBD5AF13BEF0B113E, 0x84EC3C97DA624AB4}, // 1e-34 + {0xECB1AD8AEACDD58E, 0xA6274BBDD0FADD61}, // 1e-33 + {0x67DE18EDA5814AF2, 0xCFB11EAD453994BA}, // 1e-32 + {0x80EACF948770CED7, 0x81CEB32C4B43FCF4}, // 1e-31 + {0xA1258379A94D028D, 0xA2425FF75E14FC31}, // 1e-30 + {0x096EE45813A04330, 0xCAD2F7F5359A3B3E}, // 1e-29 + {0x8BCA9D6E188853FC, 0xFD87B5F28300CA0D}, // 1e-28 + {0x775EA264CF55347D, 0x9E74D1B791E07E48}, // 1e-27 + {0x95364AFE032A819D, 0xC612062576589DDA}, // 1e-26 + {0x3A83DDBD83F52204, 0xF79687AED3EEC551}, // 1e-25 + {0xC4926A9672793542, 0x9ABE14CD44753B52}, // 1e-24 + {0x75B7053C0F178293, 0xC16D9A0095928A27}, // 1e-23 + {0x5324C68B12DD6338, 0xF1C90080BAF72CB1}, // 1e-22 + {0xD3F6FC16EBCA5E03, 0x971DA05074DA7BEE}, // 1e-21 + {0x88F4BB1CA6BCF584, 0xBCE5086492111AEA}, // 1e-20 + {0x2B31E9E3D06C32E5, 0xEC1E4A7DB69561A5}, // 1e-19 + {0x3AFF322E62439FCF, 0x9392EE8E921D5D07}, // 1e-18 + {0x09BEFEB9FAD487C2, 0xB877AA3236A4B449}, // 1e-17 + {0x4C2EBE687989A9B3, 0xE69594BEC44DE15B}, // 1e-16 + {0x0F9D37014BF60A10, 0x901D7CF73AB0ACD9}, // 1e-15 + {0x538484C19EF38C94, 0xB424DC35095CD80F}, // 1e-14 + {0x2865A5F206B06FB9, 0xE12E13424BB40E13}, // 1e-13 + {0xF93F87B7442E45D3, 0x8CBCCC096F5088CB}, // 1e-12 + {0xF78F69A51539D748, 0xAFEBFF0BCB24AAFE}, // 1e-11 + {0xB573440E5A884D1B, 0xDBE6FECEBDEDD5BE}, // 1e-10 + {0x31680A88F8953030, 0x89705F4136B4A597}, // 1e-9 + {0xFDC20D2B36BA7C3D, 0xABCC77118461CEFC}, // 1e-8 + {0x3D32907604691B4C, 0xD6BF94D5E57A42BC}, // 1e-7 + {0xA63F9A49C2C1B10F, 0x8637BD05AF6C69B5}, // 1e-6 + {0x0FCF80DC33721D53, 0xA7C5AC471B478423}, // 1e-5 + {0xD3C36113404EA4A8, 0xD1B71758E219652B}, // 1e-4 + {0x645A1CAC083126E9, 0x83126E978D4FDF3B}, // 1e-3 + {0x3D70A3D70A3D70A3, 0xA3D70A3D70A3D70A}, // 1e-2 + {0xCCCCCCCCCCCCCCCC, 0xCCCCCCCCCCCCCCCC}, // 1e-1 + {0x0000000000000000, 0x8000000000000000}, // 1e0 + {0x0000000000000000, 0xA000000000000000}, // 1e1 + {0x0000000000000000, 0xC800000000000000}, // 1e2 + {0x0000000000000000, 0xFA00000000000000}, // 1e3 + {0x0000000000000000, 0x9C40000000000000}, // 1e4 + {0x0000000000000000, 0xC350000000000000}, // 1e5 + {0x0000000000000000, 0xF424000000000000}, // 1e6 + {0x0000000000000000, 0x9896800000000000}, // 1e7 + {0x0000000000000000, 0xBEBC200000000000}, // 1e8 + {0x0000000000000000, 0xEE6B280000000000}, // 1e9 + {0x0000000000000000, 0x9502F90000000000}, // 1e10 + {0x0000000000000000, 0xBA43B74000000000}, // 1e11 + {0x0000000000000000, 0xE8D4A51000000000}, // 1e12 + {0x0000000000000000, 0x9184E72A00000000}, // 1e13 + {0x0000000000000000, 0xB5E620F480000000}, // 1e14 + {0x0000000000000000, 0xE35FA931A0000000}, // 1e15 + {0x0000000000000000, 0x8E1BC9BF04000000}, // 1e16 + {0x0000000000000000, 0xB1A2BC2EC5000000}, // 1e17 + {0x0000000000000000, 0xDE0B6B3A76400000}, // 1e18 + {0x0000000000000000, 0x8AC7230489E80000}, // 1e19 + {0x0000000000000000, 0xAD78EBC5AC620000}, // 1e20 + {0x0000000000000000, 0xD8D726B7177A8000}, // 1e21 + {0x0000000000000000, 0x878678326EAC9000}, // 1e22 + {0x0000000000000000, 0xA968163F0A57B400}, // 1e23 + {0x0000000000000000, 0xD3C21BCECCEDA100}, // 1e24 + {0x0000000000000000, 0x84595161401484A0}, // 1e25 + {0x0000000000000000, 0xA56FA5B99019A5C8}, // 1e26 + {0x0000000000000000, 0xCECB8F27F4200F3A}, // 1e27 + {0x4000000000000000, 0x813F3978F8940984}, // 1e28 + {0x5000000000000000, 0xA18F07D736B90BE5}, // 1e29 + {0xA400000000000000, 0xC9F2C9CD04674EDE}, // 1e30 + {0x4D00000000000000, 0xFC6F7C4045812296}, // 1e31 + {0xF020000000000000, 0x9DC5ADA82B70B59D}, // 1e32 + {0x6C28000000000000, 0xC5371912364CE305}, // 1e33 + {0xC732000000000000, 0xF684DF56C3E01BC6}, // 1e34 + {0x3C7F400000000000, 0x9A130B963A6C115C}, // 1e35 + {0x4B9F100000000000, 0xC097CE7BC90715B3}, // 1e36 + {0x1E86D40000000000, 0xF0BDC21ABB48DB20}, // 1e37 + {0x1314448000000000, 0x96769950B50D88F4}, // 1e38 + {0x17D955A000000000, 0xBC143FA4E250EB31}, // 1e39 + {0x5DCFAB0800000000, 0xEB194F8E1AE525FD}, // 1e40 + {0x5AA1CAE500000000, 0x92EFD1B8D0CF37BE}, // 1e41 + {0xF14A3D9E40000000, 0xB7ABC627050305AD}, // 1e42 + {0x6D9CCD05D0000000, 0xE596B7B0C643C719}, // 1e43 + {0xE4820023A2000000, 0x8F7E32CE7BEA5C6F}, // 1e44 + {0xDDA2802C8A800000, 0xB35DBF821AE4F38B}, // 1e45 + {0xD50B2037AD200000, 0xE0352F62A19E306E}, // 1e46 + {0x4526F422CC340000, 0x8C213D9DA502DE45}, // 1e47 + {0x9670B12B7F410000, 0xAF298D050E4395D6}, // 1e48 + {0x3C0CDD765F114000, 0xDAF3F04651D47B4C}, // 1e49 + {0xA5880A69FB6AC800, 0x88D8762BF324CD0F}, // 1e50 + {0x8EEA0D047A457A00, 0xAB0E93B6EFEE0053}, // 1e51 + {0x72A4904598D6D880, 0xD5D238A4ABE98068}, // 1e52 + {0x47A6DA2B7F864750, 0x85A36366EB71F041}, // 1e53 + {0x999090B65F67D924, 0xA70C3C40A64E6C51}, // 1e54 + {0xFFF4B4E3F741CF6D, 0xD0CF4B50CFE20765}, // 1e55 + {0xBFF8F10E7A8921A4, 0x82818F1281ED449F}, // 1e56 + {0xAFF72D52192B6A0D, 0xA321F2D7226895C7}, // 1e57 + {0x9BF4F8A69F764490, 0xCBEA6F8CEB02BB39}, // 1e58 + {0x02F236D04753D5B4, 0xFEE50B7025C36A08}, // 1e59 + {0x01D762422C946590, 0x9F4F2726179A2245}, // 1e60 + {0x424D3AD2B7B97EF5, 0xC722F0EF9D80AAD6}, // 1e61 + {0xD2E0898765A7DEB2, 0xF8EBAD2B84E0D58B}, // 1e62 + {0x63CC55F49F88EB2F, 0x9B934C3B330C8577}, // 1e63 + {0x3CBF6B71C76B25FB, 0xC2781F49FFCFA6D5}, // 1e64 + {0x8BEF464E3945EF7A, 0xF316271C7FC3908A}, // 1e65 + {0x97758BF0E3CBB5AC, 0x97EDD871CFDA3A56}, // 1e66 + {0x3D52EEED1CBEA317, 0xBDE94E8E43D0C8EC}, // 1e67 + {0x4CA7AAA863EE4BDD, 0xED63A231D4C4FB27}, // 1e68 + {0x8FE8CAA93E74EF6A, 0x945E455F24FB1CF8}, // 1e69 + {0xB3E2FD538E122B44, 0xB975D6B6EE39E436}, // 1e70 + {0x60DBBCA87196B616, 0xE7D34C64A9C85D44}, // 1e71 + {0xBC8955E946FE31CD, 0x90E40FBEEA1D3A4A}, // 1e72 + {0x6BABAB6398BDBE41, 0xB51D13AEA4A488DD}, // 1e73 + {0xC696963C7EED2DD1, 0xE264589A4DCDAB14}, // 1e74 + {0xFC1E1DE5CF543CA2, 0x8D7EB76070A08AEC}, // 1e75 + {0x3B25A55F43294BCB, 0xB0DE65388CC8ADA8}, // 1e76 + {0x49EF0EB713F39EBE, 0xDD15FE86AFFAD912}, // 1e77 + {0x6E3569326C784337, 0x8A2DBF142DFCC7AB}, // 1e78 + {0x49C2C37F07965404, 0xACB92ED9397BF996}, // 1e79 + {0xDC33745EC97BE906, 0xD7E77A8F87DAF7FB}, // 1e80 + {0x69A028BB3DED71A3, 0x86F0AC99B4E8DAFD}, // 1e81 + {0xC40832EA0D68CE0C, 0xA8ACD7C0222311BC}, // 1e82 + {0xF50A3FA490C30190, 0xD2D80DB02AABD62B}, // 1e83 + {0x792667C6DA79E0FA, 0x83C7088E1AAB65DB}, // 1e84 + {0x577001B891185938, 0xA4B8CAB1A1563F52}, // 1e85 + {0xED4C0226B55E6F86, 0xCDE6FD5E09ABCF26}, // 1e86 + {0x544F8158315B05B4, 0x80B05E5AC60B6178}, // 1e87 + {0x696361AE3DB1C721, 0xA0DC75F1778E39D6}, // 1e88 + {0x03BC3A19CD1E38E9, 0xC913936DD571C84C}, // 1e89 + {0x04AB48A04065C723, 0xFB5878494ACE3A5F}, // 1e90 + {0x62EB0D64283F9C76, 0x9D174B2DCEC0E47B}, // 1e91 + {0x3BA5D0BD324F8394, 0xC45D1DF942711D9A}, // 1e92 + {0xCA8F44EC7EE36479, 0xF5746577930D6500}, // 1e93 + {0x7E998B13CF4E1ECB, 0x9968BF6ABBE85F20}, // 1e94 + {0x9E3FEDD8C321A67E, 0xBFC2EF456AE276E8}, // 1e95 + {0xC5CFE94EF3EA101E, 0xEFB3AB16C59B14A2}, // 1e96 + {0xBBA1F1D158724A12, 0x95D04AEE3B80ECE5}, // 1e97 + {0x2A8A6E45AE8EDC97, 0xBB445DA9CA61281F}, // 1e98 + {0xF52D09D71A3293BD, 0xEA1575143CF97226}, // 1e99 + {0x593C2626705F9C56, 0x924D692CA61BE758}, // 1e100 + {0x6F8B2FB00C77836C, 0xB6E0C377CFA2E12E}, // 1e101 + {0x0B6DFB9C0F956447, 0xE498F455C38B997A}, // 1e102 + {0x4724BD4189BD5EAC, 0x8EDF98B59A373FEC}, // 1e103 + {0x58EDEC91EC2CB657, 0xB2977EE300C50FE7}, // 1e104 + {0x2F2967B66737E3ED, 0xDF3D5E9BC0F653E1}, // 1e105 + {0xBD79E0D20082EE74, 0x8B865B215899F46C}, // 1e106 + {0xECD8590680A3AA11, 0xAE67F1E9AEC07187}, // 1e107 + {0xE80E6F4820CC9495, 0xDA01EE641A708DE9}, // 1e108 + {0x3109058D147FDCDD, 0x884134FE908658B2}, // 1e109 + {0xBD4B46F0599FD415, 0xAA51823E34A7EEDE}, // 1e110 + {0x6C9E18AC7007C91A, 0xD4E5E2CDC1D1EA96}, // 1e111 + {0x03E2CF6BC604DDB0, 0x850FADC09923329E}, // 1e112 + {0x84DB8346B786151C, 0xA6539930BF6BFF45}, // 1e113 + {0xE612641865679A63, 0xCFE87F7CEF46FF16}, // 1e114 + {0x4FCB7E8F3F60C07E, 0x81F14FAE158C5F6E}, // 1e115 + {0xE3BE5E330F38F09D, 0xA26DA3999AEF7749}, // 1e116 + {0x5CADF5BFD3072CC5, 0xCB090C8001AB551C}, // 1e117 + {0x73D9732FC7C8F7F6, 0xFDCB4FA002162A63}, // 1e118 + {0x2867E7FDDCDD9AFA, 0x9E9F11C4014DDA7E}, // 1e119 + {0xB281E1FD541501B8, 0xC646D63501A1511D}, // 1e120 + {0x1F225A7CA91A4226, 0xF7D88BC24209A565}, // 1e121 + {0x3375788DE9B06958, 0x9AE757596946075F}, // 1e122 + {0x0052D6B1641C83AE, 0xC1A12D2FC3978937}, // 1e123 + {0xC0678C5DBD23A49A, 0xF209787BB47D6B84}, // 1e124 + {0xF840B7BA963646E0, 0x9745EB4D50CE6332}, // 1e125 + {0xB650E5A93BC3D898, 0xBD176620A501FBFF}, // 1e126 + {0xA3E51F138AB4CEBE, 0xEC5D3FA8CE427AFF}, // 1e127 + {0xC66F336C36B10137, 0x93BA47C980E98CDF}, // 1e128 + {0xB80B0047445D4184, 0xB8A8D9BBE123F017}, // 1e129 + {0xA60DC059157491E5, 0xE6D3102AD96CEC1D}, // 1e130 + {0x87C89837AD68DB2F, 0x9043EA1AC7E41392}, // 1e131 + {0x29BABE4598C311FB, 0xB454E4A179DD1877}, // 1e132 + {0xF4296DD6FEF3D67A, 0xE16A1DC9D8545E94}, // 1e133 + {0x1899E4A65F58660C, 0x8CE2529E2734BB1D}, // 1e134 + {0x5EC05DCFF72E7F8F, 0xB01AE745B101E9E4}, // 1e135 + {0x76707543F4FA1F73, 0xDC21A1171D42645D}, // 1e136 + {0x6A06494A791C53A8, 0x899504AE72497EBA}, // 1e137 + {0x0487DB9D17636892, 0xABFA45DA0EDBDE69}, // 1e138 + {0x45A9D2845D3C42B6, 0xD6F8D7509292D603}, // 1e139 + {0x0B8A2392BA45A9B2, 0x865B86925B9BC5C2}, // 1e140 + {0x8E6CAC7768D7141E, 0xA7F26836F282B732}, // 1e141 + {0x3207D795430CD926, 0xD1EF0244AF2364FF}, // 1e142 + {0x7F44E6BD49E807B8, 0x8335616AED761F1F}, // 1e143 + {0x5F16206C9C6209A6, 0xA402B9C5A8D3A6E7}, // 1e144 + {0x36DBA887C37A8C0F, 0xCD036837130890A1}, // 1e145 + {0xC2494954DA2C9789, 0x802221226BE55A64}, // 1e146 + {0xF2DB9BAA10B7BD6C, 0xA02AA96B06DEB0FD}, // 1e147 + {0x6F92829494E5ACC7, 0xC83553C5C8965D3D}, // 1e148 + {0xCB772339BA1F17F9, 0xFA42A8B73ABBF48C}, // 1e149 + {0xFF2A760414536EFB, 0x9C69A97284B578D7}, // 1e150 + {0xFEF5138519684ABA, 0xC38413CF25E2D70D}, // 1e151 + {0x7EB258665FC25D69, 0xF46518C2EF5B8CD1}, // 1e152 + {0xEF2F773FFBD97A61, 0x98BF2F79D5993802}, // 1e153 + {0xAAFB550FFACFD8FA, 0xBEEEFB584AFF8603}, // 1e154 + {0x95BA2A53F983CF38, 0xEEAABA2E5DBF6784}, // 1e155 + {0xDD945A747BF26183, 0x952AB45CFA97A0B2}, // 1e156 + {0x94F971119AEEF9E4, 0xBA756174393D88DF}, // 1e157 + {0x7A37CD5601AAB85D, 0xE912B9D1478CEB17}, // 1e158 + {0xAC62E055C10AB33A, 0x91ABB422CCB812EE}, // 1e159 + {0x577B986B314D6009, 0xB616A12B7FE617AA}, // 1e160 + {0xED5A7E85FDA0B80B, 0xE39C49765FDF9D94}, // 1e161 + {0x14588F13BE847307, 0x8E41ADE9FBEBC27D}, // 1e162 + {0x596EB2D8AE258FC8, 0xB1D219647AE6B31C}, // 1e163 + {0x6FCA5F8ED9AEF3BB, 0xDE469FBD99A05FE3}, // 1e164 + {0x25DE7BB9480D5854, 0x8AEC23D680043BEE}, // 1e165 + {0xAF561AA79A10AE6A, 0xADA72CCC20054AE9}, // 1e166 + {0x1B2BA1518094DA04, 0xD910F7FF28069DA4}, // 1e167 + {0x90FB44D2F05D0842, 0x87AA9AFF79042286}, // 1e168 + {0x353A1607AC744A53, 0xA99541BF57452B28}, // 1e169 + {0x42889B8997915CE8, 0xD3FA922F2D1675F2}, // 1e170 + {0x69956135FEBADA11, 0x847C9B5D7C2E09B7}, // 1e171 + {0x43FAB9837E699095, 0xA59BC234DB398C25}, // 1e172 + {0x94F967E45E03F4BB, 0xCF02B2C21207EF2E}, // 1e173 + {0x1D1BE0EEBAC278F5, 0x8161AFB94B44F57D}, // 1e174 + {0x6462D92A69731732, 0xA1BA1BA79E1632DC}, // 1e175 + {0x7D7B8F7503CFDCFE, 0xCA28A291859BBF93}, // 1e176 + {0x5CDA735244C3D43E, 0xFCB2CB35E702AF78}, // 1e177 + {0x3A0888136AFA64A7, 0x9DEFBF01B061ADAB}, // 1e178 + {0x088AAA1845B8FDD0, 0xC56BAEC21C7A1916}, // 1e179 + {0x8AAD549E57273D45, 0xF6C69A72A3989F5B}, // 1e180 + {0x36AC54E2F678864B, 0x9A3C2087A63F6399}, // 1e181 + {0x84576A1BB416A7DD, 0xC0CB28A98FCF3C7F}, // 1e182 + {0x656D44A2A11C51D5, 0xF0FDF2D3F3C30B9F}, // 1e183 + {0x9F644AE5A4B1B325, 0x969EB7C47859E743}, // 1e184 + {0x873D5D9F0DDE1FEE, 0xBC4665B596706114}, // 1e185 + {0xA90CB506D155A7EA, 0xEB57FF22FC0C7959}, // 1e186 + {0x09A7F12442D588F2, 0x9316FF75DD87CBD8}, // 1e187 + {0x0C11ED6D538AEB2F, 0xB7DCBF5354E9BECE}, // 1e188 + {0x8F1668C8A86DA5FA, 0xE5D3EF282A242E81}, // 1e189 + {0xF96E017D694487BC, 0x8FA475791A569D10}, // 1e190 + {0x37C981DCC395A9AC, 0xB38D92D760EC4455}, // 1e191 + {0x85BBE253F47B1417, 0xE070F78D3927556A}, // 1e192 + {0x93956D7478CCEC8E, 0x8C469AB843B89562}, // 1e193 + {0x387AC8D1970027B2, 0xAF58416654A6BABB}, // 1e194 + {0x06997B05FCC0319E, 0xDB2E51BFE9D0696A}, // 1e195 + {0x441FECE3BDF81F03, 0x88FCF317F22241E2}, // 1e196 + {0xD527E81CAD7626C3, 0xAB3C2FDDEEAAD25A}, // 1e197 + {0x8A71E223D8D3B074, 0xD60B3BD56A5586F1}, // 1e198 + {0xF6872D5667844E49, 0x85C7056562757456}, // 1e199 + {0xB428F8AC016561DB, 0xA738C6BEBB12D16C}, // 1e200 + {0xE13336D701BEBA52, 0xD106F86E69D785C7}, // 1e201 + {0xECC0024661173473, 0x82A45B450226B39C}, // 1e202 + {0x27F002D7F95D0190, 0xA34D721642B06084}, // 1e203 + {0x31EC038DF7B441F4, 0xCC20CE9BD35C78A5}, // 1e204 + {0x7E67047175A15271, 0xFF290242C83396CE}, // 1e205 + {0x0F0062C6E984D386, 0x9F79A169BD203E41}, // 1e206 + {0x52C07B78A3E60868, 0xC75809C42C684DD1}, // 1e207 + {0xA7709A56CCDF8A82, 0xF92E0C3537826145}, // 1e208 + {0x88A66076400BB691, 0x9BBCC7A142B17CCB}, // 1e209 + {0x6ACFF893D00EA435, 0xC2ABF989935DDBFE}, // 1e210 + {0x0583F6B8C4124D43, 0xF356F7EBF83552FE}, // 1e211 + {0xC3727A337A8B704A, 0x98165AF37B2153DE}, // 1e212 + {0x744F18C0592E4C5C, 0xBE1BF1B059E9A8D6}, // 1e213 + {0x1162DEF06F79DF73, 0xEDA2EE1C7064130C}, // 1e214 + {0x8ADDCB5645AC2BA8, 0x9485D4D1C63E8BE7}, // 1e215 + {0x6D953E2BD7173692, 0xB9A74A0637CE2EE1}, // 1e216 + {0xC8FA8DB6CCDD0437, 0xE8111C87C5C1BA99}, // 1e217 + {0x1D9C9892400A22A2, 0x910AB1D4DB9914A0}, // 1e218 + {0x2503BEB6D00CAB4B, 0xB54D5E4A127F59C8}, // 1e219 + {0x2E44AE64840FD61D, 0xE2A0B5DC971F303A}, // 1e220 + {0x5CEAECFED289E5D2, 0x8DA471A9DE737E24}, // 1e221 + {0x7425A83E872C5F47, 0xB10D8E1456105DAD}, // 1e222 + {0xD12F124E28F77719, 0xDD50F1996B947518}, // 1e223 + {0x82BD6B70D99AAA6F, 0x8A5296FFE33CC92F}, // 1e224 + {0x636CC64D1001550B, 0xACE73CBFDC0BFB7B}, // 1e225 + {0x3C47F7E05401AA4E, 0xD8210BEFD30EFA5A}, // 1e226 + {0x65ACFAEC34810A71, 0x8714A775E3E95C78}, // 1e227 + {0x7F1839A741A14D0D, 0xA8D9D1535CE3B396}, // 1e228 + {0x1EDE48111209A050, 0xD31045A8341CA07C}, // 1e229 + {0x934AED0AAB460432, 0x83EA2B892091E44D}, // 1e230 + {0xF81DA84D5617853F, 0xA4E4B66B68B65D60}, // 1e231 + {0x36251260AB9D668E, 0xCE1DE40642E3F4B9}, // 1e232 + {0xC1D72B7C6B426019, 0x80D2AE83E9CE78F3}, // 1e233 + {0xB24CF65B8612F81F, 0xA1075A24E4421730}, // 1e234 + {0xDEE033F26797B627, 0xC94930AE1D529CFC}, // 1e235 + {0x169840EF017DA3B1, 0xFB9B7CD9A4A7443C}, // 1e236 + {0x8E1F289560EE864E, 0x9D412E0806E88AA5}, // 1e237 + {0xF1A6F2BAB92A27E2, 0xC491798A08A2AD4E}, // 1e238 + {0xAE10AF696774B1DB, 0xF5B5D7EC8ACB58A2}, // 1e239 + {0xACCA6DA1E0A8EF29, 0x9991A6F3D6BF1765}, // 1e240 + {0x17FD090A58D32AF3, 0xBFF610B0CC6EDD3F}, // 1e241 + {0xDDFC4B4CEF07F5B0, 0xEFF394DCFF8A948E}, // 1e242 + {0x4ABDAF101564F98E, 0x95F83D0A1FB69CD9}, // 1e243 + {0x9D6D1AD41ABE37F1, 0xBB764C4CA7A4440F}, // 1e244 + {0x84C86189216DC5ED, 0xEA53DF5FD18D5513}, // 1e245 + {0x32FD3CF5B4E49BB4, 0x92746B9BE2F8552C}, // 1e246 + {0x3FBC8C33221DC2A1, 0xB7118682DBB66A77}, // 1e247 + {0x0FABAF3FEAA5334A, 0xE4D5E82392A40515}, // 1e248 + {0x29CB4D87F2A7400E, 0x8F05B1163BA6832D}, // 1e249 + {0x743E20E9EF511012, 0xB2C71D5BCA9023F8}, // 1e250 + {0x914DA9246B255416, 0xDF78E4B2BD342CF6}, // 1e251 + {0x1AD089B6C2F7548E, 0x8BAB8EEFB6409C1A}, // 1e252 + {0xA184AC2473B529B1, 0xAE9672ABA3D0C320}, // 1e253 + {0xC9E5D72D90A2741E, 0xDA3C0F568CC4F3E8}, // 1e254 + {0x7E2FA67C7A658892, 0x8865899617FB1871}, // 1e255 + {0xDDBB901B98FEEAB7, 0xAA7EEBFB9DF9DE8D}, // 1e256 + {0x552A74227F3EA565, 0xD51EA6FA85785631}, // 1e257 + {0xD53A88958F87275F, 0x8533285C936B35DE}, // 1e258 + {0x8A892ABAF368F137, 0xA67FF273B8460356}, // 1e259 + {0x2D2B7569B0432D85, 0xD01FEF10A657842C}, // 1e260 + {0x9C3B29620E29FC73, 0x8213F56A67F6B29B}, // 1e261 + {0x8349F3BA91B47B8F, 0xA298F2C501F45F42}, // 1e262 + {0x241C70A936219A73, 0xCB3F2F7642717713}, // 1e263 + {0xED238CD383AA0110, 0xFE0EFB53D30DD4D7}, // 1e264 + {0xF4363804324A40AA, 0x9EC95D1463E8A506}, // 1e265 + {0xB143C6053EDCD0D5, 0xC67BB4597CE2CE48}, // 1e266 + {0xDD94B7868E94050A, 0xF81AA16FDC1B81DA}, // 1e267 + {0xCA7CF2B4191C8326, 0x9B10A4E5E9913128}, // 1e268 + {0xFD1C2F611F63A3F0, 0xC1D4CE1F63F57D72}, // 1e269 + {0xBC633B39673C8CEC, 0xF24A01A73CF2DCCF}, // 1e270 + {0xD5BE0503E085D813, 0x976E41088617CA01}, // 1e271 + {0x4B2D8644D8A74E18, 0xBD49D14AA79DBC82}, // 1e272 + {0xDDF8E7D60ED1219E, 0xEC9C459D51852BA2}, // 1e273 + {0xCABB90E5C942B503, 0x93E1AB8252F33B45}, // 1e274 + {0x3D6A751F3B936243, 0xB8DA1662E7B00A17}, // 1e275 + {0x0CC512670A783AD4, 0xE7109BFBA19C0C9D}, // 1e276 + {0x27FB2B80668B24C5, 0x906A617D450187E2}, // 1e277 + {0xB1F9F660802DEDF6, 0xB484F9DC9641E9DA}, // 1e278 + {0x5E7873F8A0396973, 0xE1A63853BBD26451}, // 1e279 + {0xDB0B487B6423E1E8, 0x8D07E33455637EB2}, // 1e280 + {0x91CE1A9A3D2CDA62, 0xB049DC016ABC5E5F}, // 1e281 + {0x7641A140CC7810FB, 0xDC5C5301C56B75F7}, // 1e282 + {0xA9E904C87FCB0A9D, 0x89B9B3E11B6329BA}, // 1e283 + {0x546345FA9FBDCD44, 0xAC2820D9623BF429}, // 1e284 + {0xA97C177947AD4095, 0xD732290FBACAF133}, // 1e285 + {0x49ED8EABCCCC485D, 0x867F59A9D4BED6C0}, // 1e286 + {0x5C68F256BFFF5A74, 0xA81F301449EE8C70}, // 1e287 + {0x73832EEC6FFF3111, 0xD226FC195C6A2F8C}, // 1e288 + {0xC831FD53C5FF7EAB, 0x83585D8FD9C25DB7}, // 1e289 + {0xBA3E7CA8B77F5E55, 0xA42E74F3D032F525}, // 1e290 + {0x28CE1BD2E55F35EB, 0xCD3A1230C43FB26F}, // 1e291 + {0x7980D163CF5B81B3, 0x80444B5E7AA7CF85}, // 1e292 + {0xD7E105BCC332621F, 0xA0555E361951C366}, // 1e293 + {0x8DD9472BF3FEFAA7, 0xC86AB5C39FA63440}, // 1e294 + {0xB14F98F6F0FEB951, 0xFA856334878FC150}, // 1e295 + {0x6ED1BF9A569F33D3, 0x9C935E00D4B9D8D2}, // 1e296 + {0x0A862F80EC4700C8, 0xC3B8358109E84F07}, // 1e297 + {0xCD27BB612758C0FA, 0xF4A642E14C6262C8}, // 1e298 + {0x8038D51CB897789C, 0x98E7E9CCCFBD7DBD}, // 1e299 + {0xE0470A63E6BD56C3, 0xBF21E44003ACDD2C}, // 1e300 + {0x1858CCFCE06CAC74, 0xEEEA5D5004981478}, // 1e301 + {0x0F37801E0C43EBC8, 0x95527A5202DF0CCB}, // 1e302 + {0xD30560258F54E6BA, 0xBAA718E68396CFFD}, // 1e303 + {0x47C6B82EF32A2069, 0xE950DF20247C83FD}, // 1e304 + {0x4CDC331D57FA5441, 0x91D28B7416CDD27E}, // 1e305 + {0xE0133FE4ADF8E952, 0xB6472E511C81471D}, // 1e306 + {0x58180FDDD97723A6, 0xE3D8F9E563A198E5}, // 1e307 + {0x570F09EAA7EA7648, 0x8E679C2F5E44FF8F}, // 1e308 + {0x2CD2CC6551E513DA, 0xB201833B35D63F73}, // 1e309 + {0xF8077F7EA65E58D1, 0xDE81E40A034BCF4F}, // 1e310 + {0xFB04AFAF27FAF782, 0x8B112E86420F6191}, // 1e311 + {0x79C5DB9AF1F9B563, 0xADD57A27D29339F6}, // 1e312 + {0x18375281AE7822BC, 0xD94AD8B1C7380874}, // 1e313 + {0x8F2293910D0B15B5, 0x87CEC76F1C830548}, // 1e314 + {0xB2EB3875504DDB22, 0xA9C2794AE3A3C69A}, // 1e315 + {0x5FA60692A46151EB, 0xD433179D9C8CB841}, // 1e316 + {0xDBC7C41BA6BCD333, 0x849FEEC281D7F328}, // 1e317 + {0x12B9B522906C0800, 0xA5C7EA73224DEFF3}, // 1e318 + {0xD768226B34870A00, 0xCF39E50FEAE16BEF}, // 1e319 + {0xE6A1158300D46640, 0x81842F29F2CCE375}, // 1e320 + {0x60495AE3C1097FD0, 0xA1E53AF46F801C53}, // 1e321 + {0x385BB19CB14BDFC4, 0xCA5E89B18B602368}, // 1e322 + {0x46729E03DD9ED7B5, 0xFCF62C1DEE382C42}, // 1e323 + {0x6C07A2C26A8346D1, 0x9E19DB92B4E31BA9}, // 1e324 + {0xC7098B7305241885, 0xC5A05277621BE293}, // 1e325 + {0xB8CBEE4FC66D1EA7, 0xF70867153AA2DB38}, // 1e326 + {0x737F74F1DC043328, 0x9A65406D44A5C903}, // 1e327 + {0x505F522E53053FF2, 0xC0FE908895CF3B44}, // 1e328 + {0x647726B9E7C68FEF, 0xF13E34AABB430A15}, // 1e329 + {0x5ECA783430DC19F5, 0x96C6E0EAB509E64D}, // 1e330 + {0xB67D16413D132072, 0xBC789925624C5FE0}, // 1e331 + {0xE41C5BD18C57E88F, 0xEB96BF6EBADF77D8}, // 1e332 + {0x8E91B962F7B6F159, 0x933E37A534CBAAE7}, // 1e333 + {0x723627BBB5A4ADB0, 0xB80DC58E81FE95A1}, // 1e334 + {0xCEC3B1AAA30DD91C, 0xE61136F2227E3B09}, // 1e335 + {0x213A4F0AA5E8A7B1, 0x8FCAC257558EE4E6}, // 1e336 + {0xA988E2CD4F62D19D, 0xB3BD72ED2AF29E1F}, // 1e337 + {0x93EB1B80A33B8605, 0xE0ACCFA875AF45A7}, // 1e338 + {0xBC72F130660533C3, 0x8C6C01C9498D8B88}, // 1e339 + {0xEB8FAD7C7F8680B4, 0xAF87023B9BF0EE6A}, // 1e340 + {0xA67398DB9F6820E1, 0xDB68C2CA82ED2A05}, // 1e341 + {0x88083F8943A1148C, 0x892179BE91D43A43}, // 1e342 + {0x6A0A4F6B948959B0, 0xAB69D82E364948D4}, // 1e343 + {0x848CE34679ABB01C, 0xD6444E39C3DB9B09}, // 1e344 + {0xF2D80E0C0C0B4E11, 0x85EAB0E41A6940E5}, // 1e345 + {0x6F8E118F0F0E2195, 0xA7655D1D2103911F}, // 1e346 + {0x4B7195F2D2D1A9FB, 0xD13EB46469447567}, // 1e347 +} diff --git a/util/gnolanddev/strconv/ftoaryu_test.gno b/util/gnolanddev/strconv/ftoaryu_test.gno new file mode 100644 index 00000000..bd969e8e --- /dev/null +++ b/util/gnolanddev/strconv/ftoaryu_test.gno @@ -0,0 +1,30 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package strconv + +import ( + "math" + "testing" +) + +func TestMulByLog2Log10(t *testing.T) { + for x := -1600; x <= +1600; x++ { + iMath := MulByLog2Log10(x) + fMath := int(math.Floor(float64(x) * math.Ln2 / math.Ln10)) + if iMath != fMath { + t.Errorf("mulByLog2Log10(%d) failed: %d vs %d\n", x, iMath, fMath) + } + } +} + +func TestMulByLog10Log2(t *testing.T) { + for x := -500; x <= +500; x++ { + iMath := MulByLog10Log2(x) + fMath := int(math.Floor(float64(x) * math.Ln10 / math.Ln2)) + if iMath != fMath { + t.Errorf("mulByLog10Log2(%d) failed: %d vs %d\n", x, iMath, fMath) + } + } +} diff --git a/util/gnolanddev/strconv/internal_test.gno b/util/gnolanddev/strconv/internal_test.gno new file mode 100644 index 00000000..f51d4934 --- /dev/null +++ b/util/gnolanddev/strconv/internal_test.gno @@ -0,0 +1,21 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// export access to strconv internals for tests + +package strconv + +func NewDecimal(i uint64) *decimal { + d := new(decimal) + d.Assign(i) + return d +} + +func MulByLog2Log10(x int) int { + return mulByLog2Log10(x) +} + +func MulByLog10Log2(x int) int { + return mulByLog10Log2(x) +} From b85cb526cb73b5047d7eeccf1f8f4867cef3fc2b Mon Sep 17 00:00:00 2001 From: Morgan Bazalgette Date: Wed, 29 Nov 2023 21:21:18 +0100 Subject: [PATCH 02/13] split glicko2 --- {realm => package/glicko2}/glicko2.gno | 7 ++----- {realm => package/glicko2}/glicko2_test.gno | 4 ++-- package/glicko2/gno.mod | 1 + realm/chess_test.gno | 3 ++- realm/discovery.gno | 14 ++++++++------ realm/gno.mod | 1 + realm/lobby_test.gno | 4 +++- 7 files changed, 19 insertions(+), 15 deletions(-) rename {realm => package/glicko2}/glicko2.gno (96%) rename {realm => package/glicko2}/glicko2_test.gno (95%) create mode 100644 package/glicko2/gno.mod diff --git a/realm/glicko2.gno b/package/glicko2/glicko2.gno similarity index 96% rename from realm/glicko2.gno rename to package/glicko2/glicko2.gno index edcdba4e..808b9771 100644 --- a/realm/glicko2.gno +++ b/package/glicko2/glicko2.gno @@ -1,4 +1,4 @@ -package chess +package glicko2 import ( "bytes" @@ -10,9 +10,6 @@ import ( // http://www.glicko.net/glicko/glicko2.pdf -// realm global variable containing player ratings. -var playerRatings [CategoryMax][]*PlayerRating - const ( // Step 1. // Determine a rating and RD for each player at the onset of the rating period. The @@ -81,7 +78,7 @@ func getRatingScore(scores []RatingScore, player, opponent std.Address) float64 return -1 } -func updateRatings(source []*PlayerRating, scores []RatingScore) { +func UpdateRatings(source []*PlayerRating, scores []RatingScore) { // step 2: assign working wr/wrd/wrv for i, player := range source { player.wr = (player.Rating - GlickoInitialRating) / glickoScaleFactor diff --git a/realm/glicko2_test.gno b/package/glicko2/glicko2_test.gno similarity index 95% rename from realm/glicko2_test.gno rename to package/glicko2/glicko2_test.gno index 64e2089d..cf592771 100644 --- a/realm/glicko2_test.gno +++ b/package/glicko2/glicko2_test.gno @@ -1,4 +1,4 @@ -package chess +package glicko2 import ( "testing" @@ -20,7 +20,7 @@ func TestExampleCalculations(t *testing.T) { {White: "1", Black: "3", Score: 0}, {White: "1", Black: "4", Score: 0}, } - updateRatings(ratings, scores) + UpdateRatings(ratings, scores) r := ratings[0] t.Logf("%.4f (± %.4f, volatility: %.4f); working values: %.2f / %.2f / %.2f\n", r.Rating, r.RatingDeviation, r.RatingVolatility, diff --git a/package/glicko2/gno.mod b/package/glicko2/gno.mod new file mode 100644 index 00000000..f89cecf7 --- /dev/null +++ b/package/glicko2/gno.mod @@ -0,0 +1 @@ +module gno.land/p/demo/chess/glicko2 diff --git a/realm/chess_test.gno b/realm/chess_test.gno index 337f389b..b40743f2 100644 --- a/realm/chess_test.gno +++ b/realm/chess_test.gno @@ -12,6 +12,7 @@ import ( "gno.land/p/demo/avl" "gno.land/p/demo/chess" + "gno.land/p/demo/chess/glicko2" ) func cleanup() { @@ -22,7 +23,7 @@ func cleanup() { leaderboard = [CategoryMax]leaderboardType{} lobby = [tcLobbyMax][]lobbyPlayer{} lobbyPlayer2Game = avl.Tree{} - playerRatings = [CategoryMax][]*PlayerRating{} + playerRatings = [CategoryMax][]*glicko2.PlayerRating{} } func TestNewGame(t *testing.T) { diff --git a/realm/discovery.gno b/realm/discovery.gno index f98e7490..db8b58f7 100644 --- a/realm/discovery.gno +++ b/realm/discovery.gno @@ -11,6 +11,7 @@ import ( "strings" "gno.land/p/demo/avl" + "gno.land/p/demo/chess/glicko2" "gno.land/r/demo/users" ) @@ -70,8 +71,9 @@ func (tc *TimeControl) Category() Category { // realm state var ( - playerStore avl.Tree // std.Address -> *Player - leaderboard [CategoryMax]leaderboardType + playerStore avl.Tree // std.Address -> *Player + leaderboard [CategoryMax]leaderboardType + playerRatings [CategoryMax][]*glicko2.PlayerRating ) func GetPlayer(player string) string { @@ -93,7 +95,7 @@ type Player struct { type CategoryInfo struct { Wins, Losses, Draws int - *PlayerRating + *glicko2.PlayerRating } // Score for determining leaderboards. @@ -174,7 +176,7 @@ func (g *Game) saveResult() { // Call glicko 2 rating calculator. owr, obr := w.CategoryInfo[cat].Rating, b.CategoryInfo[cat].Rating - updateRatings(playerRatings[cat], []RatingScore{{ + glicko2.UpdateRatings(playerRatings[cat], []glicko2.RatingScore{{ White: g.White, Black: g.Black, Score: result, @@ -195,12 +197,12 @@ func getPlayer(addr std.Address) *Player { p := new(Player) p.Address = addr for _, cat := range categoryList { - pr := NewPlayerRating(addr) + pr := glicko2.NewPlayerRating(addr) p.CategoryInfo[cat] = CategoryInfo{ PlayerRating: pr, } // https://github.com/gnolang/gno/pull/1170 - prs := append([]*PlayerRating{}, playerRatings[cat]...) + prs := append([]*glicko2.PlayerRating{}, playerRatings[cat]...) playerRatings[cat] = append(prs, pr) } playerStore.Set(addr.String(), p) diff --git a/realm/gno.mod b/realm/gno.mod index f07b5f13..baa239fa 100644 --- a/realm/gno.mod +++ b/realm/gno.mod @@ -3,6 +3,7 @@ module gno.land/r/demo/chess require ( "gno.land/p/demo/avl" v0.0.0-latest "gno.land/p/demo/chess" v0.0.0-latest + "gno.land/p/demo/chess/glicko2" v0.0.0-latest "gno.land/p/demo/ufmt" v0.0.0-latest "gno.land/r/demo/users" v0.0.0-latest ) diff --git a/realm/lobby_test.gno b/realm/lobby_test.gno index dba1f223..2df41a5e 100644 --- a/realm/lobby_test.gno +++ b/realm/lobby_test.gno @@ -8,6 +8,8 @@ import ( "time" "internal/os_test" + + "gno.land/p/demo/chess/glicko2" ) func TestLobbyJoin(t *testing.T) { @@ -147,7 +149,7 @@ func TestLobbyGameFound(t *testing.T) { player: &Player{ Address: p.id, CategoryInfo: [CategoryMax]CategoryInfo{ - Blitz: {PlayerRating: &PlayerRating{Rating: p.rating}}, + Blitz: {PlayerRating: &glicko2.PlayerRating{Rating: p.rating}}, }, }, }) From cd592194df1220bf008b69782f05e80be6357542 Mon Sep 17 00:00:00 2001 From: Morgan Bazalgette Date: Wed, 29 Nov 2023 21:48:49 +0100 Subject: [PATCH 03/13] shuffle things around --- realm/chess.gno | 6 ++++++ realm/lobby.gno | 13 ------------- realm/util.gno | 7 ------- 3 files changed, 6 insertions(+), 20 deletions(-) delete mode 100644 realm/util.gno diff --git a/realm/chess.gno b/realm/chess.gno index 550dee08..703dda90 100644 --- a/realm/chess.gno +++ b/realm/chess.gno @@ -635,3 +635,9 @@ func Draw(gameID string) string { return g.json() } + +func checkErr(err error) { + if err != nil { + panic(err.Error()) + } +} diff --git a/realm/lobby.gno b/realm/lobby.gno index ed0ec639..e9b6ff3e 100644 --- a/realm/lobby.gno +++ b/realm/lobby.gno @@ -64,19 +64,6 @@ var ( lobbyPlayer2Game avl.Tree // player addr -> *Game. set after a user is matched; reset when joining again. ) -// XXX: REMOVE BEFORE PRODUCTION -func LobbyData() string { - var buf bytes.Buffer - for idx, sublob := range lobby { - buf.WriteString("Sublobby " + strconv.Itoa(idx)) - for _, player := range sublob { - buf.WriteString("- " + player.player.Address.String()) - } - buf.WriteByte('\n') - } - return buf.String() -} - func LobbyJoin(seconds, increment int) { std.AssertOriginCall() diff --git a/realm/util.gno b/realm/util.gno deleted file mode 100644 index d9dc9192..00000000 --- a/realm/util.gno +++ /dev/null @@ -1,7 +0,0 @@ -package chess - -func checkErr(err error) { - if err != nil { - panic(err.Error()) - } -} From af797fc3f9f286e128ef5b8ba0d3677643f3e063 Mon Sep 17 00:00:00 2001 From: Morgan Bazalgette Date: Fri, 9 Feb 2024 12:57:23 +0100 Subject: [PATCH 04/13] re-implement using gnodev --- .github/workflows/realm.yml | 2 +- .gitignore | 1 + Makefile | 32 + go.mod | 57 +- go.sum | 191 ++- package/glicko2/glicko2.gno | 26 +- realm/chess.gno | 22 +- realm/chess_test.gno | 1 + util/gnoimport.go | 1 + util/gnolanddev/strconv/decimal.gno | 415 ------- util/gnolanddev/strconv/decimal_test.gno | 126 -- util/gnolanddev/strconv/ftoa.gno | 702 ----------- util/gnolanddev/strconv/ftoa_test.gno | 275 ----- util/gnolanddev/strconv/ftoaryu.gno | 1280 --------------------- util/gnolanddev/strconv/ftoaryu_test.gno | 30 - util/gnolanddev/strconv/internal_test.gno | 21 - 16 files changed, 256 insertions(+), 2926 deletions(-) delete mode 100644 util/gnolanddev/strconv/decimal.gno delete mode 100644 util/gnolanddev/strconv/decimal_test.gno delete mode 100644 util/gnolanddev/strconv/ftoa.gno delete mode 100644 util/gnolanddev/strconv/ftoa_test.gno delete mode 100644 util/gnolanddev/strconv/ftoaryu.gno delete mode 100644 util/gnolanddev/strconv/ftoaryu_test.gno delete mode 100644 util/gnolanddev/strconv/internal_test.gno diff --git a/.github/workflows/realm.yml b/.github/workflows/realm.yml index 498e717e..bf3d3fe7 100644 --- a/.github/workflows/realm.yml +++ b/.github/workflows/realm.yml @@ -21,4 +21,4 @@ jobs: with: go-version: 'stable' - run: go mod download -x - - run: go run github.com/gnolang/gno/gnovm/cmd/gno test -verbose -run 'Test([^P]|P[^e])' ./realm + - run: go run github.com/gnolang/gno/gnovm/cmd/gno test -verbose ./realm diff --git a/.gitignore b/.gitignore index bd126f13..6f4b5a61 100644 --- a/.gitignore +++ b/.gitignore @@ -124,6 +124,7 @@ realm/*.go .*.gen.go *.gen_test.go *.vim +/.test .tmp/ # Local Netlify folder diff --git a/Makefile b/Makefile index 73fbdac7..f8782376 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,43 @@ +.PHONY: default default: help GNOKEY ?= go run github.com/gnolang/gno/gno.land/cmd/gnokey GNOLAND ?= go run github.com/gnolang/gno/gno.land/cmd/gnoland +GNODEV ?= go run github.com/gnolang/gno/contribs/gnodev +GNOROOT ?= `gno env GNOROOT` +GNO_TEST_FLAGS ?= -verbose -run '^Test(?:[^P]|P[^e]|Pe[^r])' +GNO_TEST_PKGS ?= gno.land/p/demo/chess/... gno.land/r/demo/chess + +.PHONY: help help: ## Display this help message. @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[0-9a-zA-Z_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 }' $(MAKEFILE_LIST) +.PHONY: dev +dev: + $(GNODEV) ./package/glicko2 ./package/zobrist ./package ./realm + +.PHONY: clean +clean: + find . -name '*.gen.go' -exec rm -rf {} + + +.PHONY: test +test: + rm -rf .test + # Create fake GNOROOT with stdlibs, testing stdlibs, and p/ dependencies. + # This is currently necessary as gno.mod's `replace` functionality is not linked with the VM. + mkdir -p .test/gnovm/tests .test/examples/gno.land/p/demo .test/examples/gno.land/r/demo + cp -r "$(GNOROOT)/gnovm/stdlibs" .test/gnovm/stdlibs + cp -r "$(GNOROOT)/gnovm/tests/stdlibs" .test/gnovm/tests/stdlibs + for i in gno.land/p/demo/ufmt gno.land/p/demo/avl gno.land/r/demo/users; do \ + cp -r "$(GNOROOT)/examples/$$i" ".test/examples/$$i";\ + done + # Copy over gnochess code. + cp -r "$(PWD)/package" ".test/examples/gno.land/p/demo/chess" + cp -r "$(PWD)/realm" ".test/examples/gno.land/r/demo/chess" + # Test. + cd .test/examples; GNOROOT="$(PWD)/.test" gno test $(GNO_TEST_FLAGS) $(GNO_TEST_PKGS) + 0_setup_gnokey: ## Add an account that will be used for Realm deployment (to gnokey). printf '\n\n%s\n\n' "source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast" | $(GNOKEY) add --recover --insecure-password-stdin DeployKey || true $(GNOKEY) list | grep DeployKey diff --git a/go.mod b/go.mod index 1f13ae4e..454c4807 100644 --- a/go.mod +++ b/go.mod @@ -1,53 +1,70 @@ module github.com/gnolang/gnochess -go 1.20 +go 1.21 require ( - github.com/gnolang/gno v0.0.0-20230926053156-5c40bc5a7984 + github.com/gnolang/gno v0.0.0-20240208173614-9734695c3b17 + github.com/gnolang/gno/contribs/gnodev v0.0.0-20240208173614-9734695c3b17 github.com/jaekwon/testify v1.6.1 github.com/rogpeppe/go-internal v1.11.0 ) require ( - github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c // indirect - github.com/btcsuite/btcd/btcutil v1.0.0 // indirect + dario.cat/mergo v1.0.0 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect + github.com/btcsuite/btcd/btcutil v1.1.3 // indirect github.com/cespare/xxhash v1.1.0 // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect - github.com/cockroachdb/apd v1.1.0 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cockroachdb/apd/v3 v3.2.1 // indirect + github.com/cosmos/ledger-cosmos-go v0.13.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/dgraph-io/badger/v3 v3.2103.4 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect + github.com/dgraph-io/badger/v3 v3.2103.5 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dustin/go-humanize v1.0.0 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/gnolang/goleveldb v0.0.9 // indirect github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect + github.com/golang/glog v1.1.0 // indirect github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect github.com/google/flatbuffers v1.12.1 // indirect - github.com/gorilla/websocket v1.5.0 // indirect + github.com/gorilla/mux v1.8.1 // indirect + github.com/gorilla/securecookie v1.1.1 // indirect + github.com/gorilla/sessions v1.2.1 // indirect + github.com/gorilla/websocket v1.5.1 // indirect + github.com/gotuna/gotuna v0.6.0 // indirect github.com/jmhodges/levigo v1.0.0 // indirect github.com/klauspost/compress v1.12.3 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect - github.com/linxGnu/grocksdb v1.8.4 // indirect + github.com/linxGnu/grocksdb v1.8.11 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/peterbourgon/ff/v3 v3.4.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rs/cors v1.10.0 // indirect + github.com/rs/cors v1.10.1 // indirect github.com/stretchr/testify v1.8.4 // indirect github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect - go.etcd.io/bbolt v1.3.7 // indirect + github.com/zondax/hid v0.9.2 // indirect + github.com/zondax/ledger-go v0.14.3 // indirect + go.etcd.io/bbolt v1.3.8 // indirect go.opencensus.io v0.22.5 // indirect - go.uber.org/atomic v1.7.0 // indirect - go.uber.org/multierr v1.9.0 // indirect - golang.org/x/crypto v0.13.0 // indirect - golang.org/x/mod v0.12.0 // indirect - golang.org/x/net v0.15.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/term v0.12.0 // indirect - golang.org/x/tools v0.6.0 // indirect + go.uber.org/atomic v1.10.0 // indirect + go.uber.org/multierr v1.10.0 // indirect + go.uber.org/zap v1.24.0 // indirect + go.uber.org/zap/exp v0.1.0 // indirect + golang.org/x/crypto v0.18.0 // indirect + golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 // indirect + golang.org/x/mod v0.14.0 // indirect + golang.org/x/net v0.20.0 // indirect + golang.org/x/sys v0.16.0 // indirect + golang.org/x/term v0.16.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/tools v0.17.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c // indirect + google.golang.org/grpc v1.58.3 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index a03fe362..1ee71b27 100644 --- a/go.sum +++ b/go.sum @@ -1,39 +1,65 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= -github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c h1:lnAMg3ra/Gw4AkRMxrxYs8nrprWsHowg8H9zaYsJOo4= github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= -github.com/btcsuite/btcd/btcutil v1.0.0 h1:dB36qRTOucIh6NUe40UCieOS+axPhP6VNyRtYkTUKKk= +github.com/btcsuite/btcd v0.23.0 h1:V2/ZgjfDFIygAX3ZapeigkVBoVUtOJKSwrhZdlpSvaA= +github.com/btcsuite/btcd v0.23.0/go.mod h1:0QJIIN1wwIXF/3G/m87gIwGniDMDQqjVn4SZgnFpsYY= +github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= +github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= +github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= +github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= +github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ= +github.com/btcsuite/btcd/btcutil v1.1.3/go.mod h1:UR7dsSJzJUfMmFiiLlIrMq1lS9jh9EdCV7FStZSnpi0= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2 h1:KdUfX2zKommPRa+PD0sWZUyXe9w277ABlgELO7H04IM= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.2/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/btcutil v1.0.2 h1:9iZ1Terx9fMIOtq1VrwdqfsATL9MC2l8ZrUY6YZ2uts= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= -github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= +github.com/cockroachdb/apd/v3 v3.2.1 h1:U+8j7t0axsIgvQUqthuNm82HIrYXodOV2iWLWtEaIwg= +github.com/cockroachdb/apd/v3 v3.2.1/go.mod h1:klXJcjp+FffLTHlhIG69tezTDvdP065naDsHzKhYSqc= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cosmos/ledger-cosmos-go v0.13.3 h1:7ehuBGuyIytsXbd4MP43mLeoN2LTOEnk5nvue4rK+yM= +github.com/cosmos/ledger-cosmos-go v0.13.3/go.mod h1:HENcEP+VtahZFw38HZ3+LS3Iv5XV6svsnkk9vdJtLr8= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgraph-io/badger/v3 v3.2103.4 h1:WE1B07YNTTJTtG9xjBcSW2wn0RJLyiV99h959RKZqM4= -github.com/dgraph-io/badger/v3 v3.2103.4/go.mod h1:4MPiseMeDQ3FNCYwRbbcBOGJLf5jsE0PPFzRiKjtcdw= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/dgraph-io/badger/v3 v3.2103.5 h1:ylPa6qzbjYRQMU6jokoj4wzcaweHylt//CH0AKt0akg= +github.com/dgraph-io/badger/v3 v3.2103.5/go.mod h1:4MPiseMeDQ3FNCYwRbbcBOGJLf5jsE0PPFzRiKjtcdw= github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA= @@ -41,30 +67,41 @@ github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUn github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0= +github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64= github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= +github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg= github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= +github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= -github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/gnolang/gno v0.0.0-20230925211159-9c7c0a577eb6 h1:6r5rPQtx5yV3X3+zJzqVBdN3HAcUO9MwCI0TJ3lgCmU= -github.com/gnolang/gno v0.0.0-20230925211159-9c7c0a577eb6/go.mod h1:dtwSoPiPCcGxACg4y2iJVWZ/vuU133n4kwF28mx6Krg= -github.com/gnolang/gno v0.0.0-20230926003128-2a9e425470d1 h1:MqpejgKbMfC26A9w+JVCu81ilnlVdg8C6SXlIM6GiJE= -github.com/gnolang/gno v0.0.0-20230926003128-2a9e425470d1/go.mod h1:dtwSoPiPCcGxACg4y2iJVWZ/vuU133n4kwF28mx6Krg= -github.com/gnolang/gno v0.0.0-20230926053156-5c40bc5a7984 h1:VCnWFnSz5yL5vOBdLdJza/o4D95sO8RnFcb3qIZgWdY= -github.com/gnolang/gno v0.0.0-20230926053156-5c40bc5a7984/go.mod h1:dtwSoPiPCcGxACg4y2iJVWZ/vuU133n4kwF28mx6Krg= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/gnolang/gno v0.0.0-20240208173614-9734695c3b17 h1:HzGOcZg/+KjZMTuvlApX84NfCUim4hSJcqB0elpckPc= +github.com/gnolang/gno v0.0.0-20240208173614-9734695c3b17/go.mod h1:pzlpRF80RfVsWpstEumplkhDnAhzkbgSpoVOio3jkJs= +github.com/gnolang/gno/contribs/gnodev v0.0.0-20240208173614-9734695c3b17 h1:CnudmmHlFJic9Mpbj0P5hBAFH+Pzv/NTU0BJzMw2VfA= +github.com/gnolang/gno/contribs/gnodev v0.0.0-20240208173614-9734695c3b17/go.mod h1:X/DDvLnu7m/bbvaccoTbpWNwGXjxWx1FtdWnO4cpv7E= github.com/gnolang/goleveldb v0.0.9 h1:Q7rGko9oXMKtQA+Apeeed5a3sjba/mcDhzJGoTVLCKE= github.com/gnolang/goleveldb v0.0.9/go.mod h1:Dz6p9bmpy/FBESTgduiThZt5mToVDipcHGzj/zUOo8E= github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216 h1:GKvsK3oLWG9B1GL7WP/VqwM6C92j5tIvB844oggL9Lk= github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216/go.mod h1:xJhtEL7ahjM1WJipt89gel8tHzfIl/LyMY+lCYh38d8= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= +github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= @@ -74,18 +111,33 @@ github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/google/flatbuffers v1.12.1 h1:MVlul7pQNoDzWRLTw5imwYsl+usrS1TXG2H4jg6ImGw= github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gorilla/csrf v1.7.0/go.mod h1:+a/4tCmqhG6/w4oafeAZ9pEa3/NZOWYVbD9fV0FwIQA= +github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= +github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= +github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI= +github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= +github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= +github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/gotuna/gotuna v0.6.0 h1:N1lQKXEi/lwRp8u3sccTYLhzOffA4QasExz/1M5Riws= +github.com/gotuna/gotuna v0.6.0/go.mod h1:F/ecRt29ChB6Ycy1AFIBpBiMNK0j7Heq+gFbLWquhjc= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jaekwon/testify v1.6.1 h1:4AtAJcR9GzXN5W4DdY7ie74iCPiJV1JJUJL90t2ZUyw= github.com/jaekwon/testify v1.6.1/go.mod h1:Oun0RXIHI7osufabQ60i4Lqkj0GXLbqI1I7kgzBNm1U= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= @@ -94,25 +146,35 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.12.3 h1:G5AfA94pHPysR56qqrkO2pxEexdDzrpFJ6yt/VqWxVU= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= +github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= -github.com/linxGnu/grocksdb v1.8.4 h1:ZMsBpPpJNtRLHiKKp0mI7gW+NT4s7UgfD5xHxx1jVRo= -github.com/linxGnu/grocksdb v1.8.4/go.mod h1:xZCIb5Muw+nhbDK4Y5UJuOrin5MceOuiXkVUR7vp4WY= +github.com/linxGnu/grocksdb v1.8.11 h1:BGol9e5gB1BrsTvOxloC88pe70TCqgrfLNwkyWW0kD8= +github.com/linxGnu/grocksdb v1.8.11/go.mod h1:xZCIb5Muw+nhbDK4Y5UJuOrin5MceOuiXkVUR7vp4WY= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY= +github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= @@ -124,8 +186,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= -github.com/rs/cors v1.10.0 h1:62NOS1h+r8p1mW6FM0FSB0exioXLhd/sh15KpjWBZ+8= -github.com/rs/cors v1.10.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= +github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= @@ -137,42 +199,55 @@ github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb6 github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok= github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= -go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= +github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= +github.com/zondax/hid v0.9.2/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= +github.com/zondax/ledger-go v0.14.3 h1:wEpJt2CEcBJ428md/5MgSLsXLBos98sBOyxNmCjfUCw= +github.com/zondax/ledger-go v0.14.3/go.mod h1:IKKaoxupuB43g4NxeQmbLXv7T9AlQyie1UpHb342ycI= +go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= +go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.opencensus.io v0.22.5 h1:dntmOdLpSpHlVqbW5Eay97DelsZHe+55D+xC6i0dDS0= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= -go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= -go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= +go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= +go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +go.uber.org/zap/exp v0.1.0 h1:Ol9zQNvAEAgFHSBiR5LlwS9Xq8u5QF+7HBwNHUB8rcI= +go.uber.org/zap/exp v0.1.0/go.mod h1:z/0T3As39ttolxZGOsvk1OEvQfwwfTZpmV9YTp+VAkc= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= -golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= +golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o= +golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -181,9 +256,11 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= -golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= +golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -197,15 +274,23 @@ golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= +golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -213,8 +298,8 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= +golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -224,8 +309,18 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c h1:jHkCUWkseRf+W+edG5hMzr/Uh1xkDREY4caybAq4dpY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c/go.mod h1:4cYg8o5yUbm77w8ZX00LhMVNl/YVBFJRYWDc0uYWMs0= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= +google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= @@ -233,12 +328,16 @@ google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/package/glicko2/glicko2.gno b/package/glicko2/glicko2.gno index 808b9771..45ab44c8 100644 --- a/package/glicko2/glicko2.gno +++ b/package/glicko2/glicko2.gno @@ -53,13 +53,33 @@ func NewPlayerRating(addr std.Address) *PlayerRating { func (p PlayerRating) MarshalJSON() ([]byte, error) { var buf bytes.Buffer buf.WriteByte('{') - buf.WriteString(`"rating":` + strconv.FormatFloat(p.Rating, 'f', -1, 64) + `,`) - buf.WriteString(`"deviation":` + strconv.FormatFloat(p.RatingDeviation, 'f', -1, 64) + `,`) - buf.WriteString(`"volatility":` + strconv.FormatFloat(p.RatingVolatility, 'f', -1, 64)) + buf.WriteString(`"rating":` + formatFloat(p.Rating, 5) + `,`) + buf.WriteString(`"deviation":` + formatFloat(p.RatingDeviation, 5) + `,`) + buf.WriteString(`"volatility":` + formatFloat(p.RatingVolatility, 5)) buf.WriteByte('}') return buf.Bytes(), nil } +// XXX: dumb formatFloat implementation while we don't have strconv.FormatFloat +// https://github.com/gnolang/gno/pull/1464 +func formatFloat(f float64, decimals int) string { + if decimals > 10 { + decimals = 10 + } + neg := "" + if f < 0 { + f *= -1 + neg = "-" + } + const zeroes = "0000000000" // 10 zeroes + whole := math.Floor(f) + fractional := f - whole + leading := strconv.Itoa(int(whole)) + trailing := strconv.Itoa(int(fractional * 1e10)) + trailing = zeroes[:10-len(trailing)] + trailing + return neg + leading + "." + trailing +} + // RatingScore is the outcome of a game between two players. type RatingScore struct { White, Black std.Address diff --git a/realm/chess.gno b/realm/chess.gno index 703dda90..4961a18e 100644 --- a/realm/chess.gno +++ b/realm/chess.gno @@ -216,7 +216,7 @@ func (g GameState) IsFinished() bool { // parallel games OR by introducing a "request" system, so that a game is not // immediately considered "open" when calling NewGame. func xNewGame(opponentRaw string, seconds, increment int) string { - std.AssertOriginCall() + assertOriginCall() if seconds >= 0 && increment < 0 { panic("negative increment invalid") @@ -355,7 +355,7 @@ func getGame(id string, wantOpen bool) *Game { // must be specified. // Castling is specified by indicating the king's movement. func MakeMove(gameID, from, to string, promote chess.Piece) string { - std.AssertOriginCall() + assertOriginCall() g := getGame(gameID, true) @@ -492,7 +492,7 @@ func ClaimTimeout(gameID string) string { } func Abort(gameID string) string { - std.AssertOriginCall() + assertOriginCall() g := getGame(gameID, true) err := abort(g) @@ -520,7 +520,7 @@ func abort(g *Game) error { } func Resign(gameID string) string { - std.AssertOriginCall() + assertOriginCall() g := getGame(gameID, true) err := resign(g) @@ -554,7 +554,7 @@ func resign(g *Game) error { // DrawOffer creates a draw offer in the current game, if one doesn't already // exist. func DrawOffer(gameID string) string { - std.AssertOriginCall() + assertOriginCall() g := getGame(gameID, true) caller := std.GetOrigCaller() @@ -572,7 +572,7 @@ func DrawOffer(gameID string) string { // DrawRefuse refuse a draw offer in the given game. func DrawRefuse(gameID string) string { - std.AssertOriginCall() + assertOriginCall() g := getGame(gameID, true) caller := std.GetOrigCaller() @@ -596,7 +596,7 @@ func DrawRefuse(gameID string) string { // - Insufficient material (§9.4) // Note: stalemate happens as a consequence of a Move, and thus is handled in that function. func Draw(gameID string) string { - std.AssertOriginCall() + assertOriginCall() g := getGame(gameID, true) @@ -641,3 +641,11 @@ func checkErr(err error) { panic(err.Error()) } } + +// Replacement for OriginCall using std.PrevRealm(). +// See: https://github.com/gnolang/gno/pull/1048 +func assertOriginCall() { + if !std.PrevRealm().IsUser() { + panic("invalid non-origin call") + } +} diff --git a/realm/chess_test.gno b/realm/chess_test.gno index b40743f2..e0f91296 100644 --- a/realm/chess_test.gno +++ b/realm/chess_test.gno @@ -600,6 +600,7 @@ func runCommandTest(t *testing.T, command string) { func catchPanic(tc testCommandRunner, t *testing.T, bufs map[string]string) { defer func() { + // XXX: should prefer testing.Recover, but see: https://github.com/gnolang/gno/issues/1650 e := recover() if e == nil { bufs["panic"] = "" diff --git a/util/gnoimport.go b/util/gnoimport.go index 6ab8198c..84321ffb 100644 --- a/util/gnoimport.go +++ b/util/gnoimport.go @@ -5,6 +5,7 @@ package main import ( + _ "github.com/gnolang/gno/contribs/gnodev" _ "github.com/gnolang/gno/gno.land/cmd/gnokey" _ "github.com/gnolang/gno/gnovm/cmd/gno" ) diff --git a/util/gnolanddev/strconv/decimal.gno b/util/gnolanddev/strconv/decimal.gno deleted file mode 100644 index b5800188..00000000 --- a/util/gnolanddev/strconv/decimal.gno +++ /dev/null @@ -1,415 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Multiprecision decimal numbers. -// For floating-point formatting only; not general purpose. -// Only operations are assign and (binary) left/right shift. -// Can do binary floating point in multiprecision decimal precisely -// because 2 divides 10; cannot do decimal floating point -// in multiprecision binary precisely. - -package strconv - -type decimal struct { - d [800]byte // digits, big-endian representation - nd int // number of digits used - dp int // decimal point - neg bool // negative flag - trunc bool // discarded nonzero digits beyond d[:nd] -} - -func (a *decimal) String() string { - n := 10 + a.nd - if a.dp > 0 { - n += a.dp - } - if a.dp < 0 { - n += -a.dp - } - - buf := make([]byte, n) - w := 0 - switch { - case a.nd == 0: - return "0" - - case a.dp <= 0: - // zeros fill space between decimal point and digits - buf[w] = '0' - w++ - buf[w] = '.' - w++ - w += digitZero(buf[w : w+-a.dp]) - w += copy(buf[w:], a.d[0:a.nd]) - - case a.dp < a.nd: - // decimal point in middle of digits - w += copy(buf[w:], a.d[0:a.dp]) - buf[w] = '.' - w++ - w += copy(buf[w:], a.d[a.dp:a.nd]) - - default: - // zeros fill space between digits and decimal point - w += copy(buf[w:], a.d[0:a.nd]) - w += digitZero(buf[w : w+a.dp-a.nd]) - } - return string(buf[0:w]) -} - -func digitZero(dst []byte) int { - for i := range dst { - dst[i] = '0' - } - return len(dst) -} - -// trim trailing zeros from number. -// (They are meaningless; the decimal point is tracked -// independent of the number of digits.) -func trim(a *decimal) { - for a.nd > 0 && a.d[a.nd-1] == '0' { - a.nd-- - } - if a.nd == 0 { - a.dp = 0 - } -} - -// Assign v to a. -func (a *decimal) Assign(v uint64) { - var buf [24]byte - - // Write reversed decimal in buf. - n := 0 - for v > 0 { - v1 := v / 10 - v -= 10 * v1 - buf[n] = byte(v + '0') - n++ - v = v1 - } - - // Reverse again to produce forward decimal in a.d. - a.nd = 0 - for n--; n >= 0; n-- { - a.d[a.nd] = buf[n] - a.nd++ - } - a.dp = a.nd - trim(a) -} - -// Maximum shift that we can do in one pass without overflow. -// A uint has 32 or 64 bits, and we have to be able to accommodate 9<> 63) -const maxShift = uintSize - 4 - -// Binary shift right (/ 2) by k bits. k <= maxShift to avoid overflow. -func rightShift(a *decimal, k uint) { - r := 0 // read pointer - w := 0 // write pointer - - // Pick up enough leading digits to cover first shift. - var n uint - for ; n>>k == 0; r++ { - if r >= a.nd { - if n == 0 { - // a == 0; shouldn't get here, but handle anyway. - a.nd = 0 - return - } - for n>>k == 0 { - n = n * 10 - r++ - } - break - } - c := uint(a.d[r]) - n = n*10 + c - '0' - } - a.dp -= r - 1 - - var mask uint = (1 << k) - 1 - - // Pick up a digit, put down a digit. - for ; r < a.nd; r++ { - c := uint(a.d[r]) - dig := n >> k - n &= mask - a.d[w] = byte(dig + '0') - w++ - n = n*10 + c - '0' - } - - // Put down extra digits. - for n > 0 { - dig := n >> k - n &= mask - if w < len(a.d) { - a.d[w] = byte(dig + '0') - w++ - } else if dig > 0 { - a.trunc = true - } - n = n * 10 - } - - a.nd = w - trim(a) -} - -// Cheat sheet for left shift: table indexed by shift count giving -// number of new digits that will be introduced by that shift. -// -// For example, leftcheats[4] = {2, "625"}. That means that -// if we are shifting by 4 (multiplying by 16), it will add 2 digits -// when the string prefix is "625" through "999", and one fewer digit -// if the string prefix is "000" through "624". -// -// Credit for this trick goes to Ken. - -type leftCheat struct { - delta int // number of new digits - cutoff string // minus one digit if original < a. -} - -var leftcheats = []leftCheat{ - // Leading digits of 1/2^i = 5^i. - // 5^23 is not an exact 64-bit floating point number, - // so have to use bc for the math. - // Go up to 60 to be large enough for 32bit and 64bit platforms. - /* - seq 60 | sed 's/^/5^/' | bc | - awk 'BEGIN{ print "\t{ 0, \"\" }," } - { - log2 = log(2)/log(10) - printf("\t{ %d, \"%s\" },\t// * %d\n", - int(log2*NR+1), $0, 2**NR) - }' - */ - {0, ""}, - {1, "5"}, // * 2 - {1, "25"}, // * 4 - {1, "125"}, // * 8 - {2, "625"}, // * 16 - {2, "3125"}, // * 32 - {2, "15625"}, // * 64 - {3, "78125"}, // * 128 - {3, "390625"}, // * 256 - {3, "1953125"}, // * 512 - {4, "9765625"}, // * 1024 - {4, "48828125"}, // * 2048 - {4, "244140625"}, // * 4096 - {4, "1220703125"}, // * 8192 - {5, "6103515625"}, // * 16384 - {5, "30517578125"}, // * 32768 - {5, "152587890625"}, // * 65536 - {6, "762939453125"}, // * 131072 - {6, "3814697265625"}, // * 262144 - {6, "19073486328125"}, // * 524288 - {7, "95367431640625"}, // * 1048576 - {7, "476837158203125"}, // * 2097152 - {7, "2384185791015625"}, // * 4194304 - {7, "11920928955078125"}, // * 8388608 - {8, "59604644775390625"}, // * 16777216 - {8, "298023223876953125"}, // * 33554432 - {8, "1490116119384765625"}, // * 67108864 - {9, "7450580596923828125"}, // * 134217728 - {9, "37252902984619140625"}, // * 268435456 - {9, "186264514923095703125"}, // * 536870912 - {10, "931322574615478515625"}, // * 1073741824 - {10, "4656612873077392578125"}, // * 2147483648 - {10, "23283064365386962890625"}, // * 4294967296 - {10, "116415321826934814453125"}, // * 8589934592 - {11, "582076609134674072265625"}, // * 17179869184 - {11, "2910383045673370361328125"}, // * 34359738368 - {11, "14551915228366851806640625"}, // * 68719476736 - {12, "72759576141834259033203125"}, // * 137438953472 - {12, "363797880709171295166015625"}, // * 274877906944 - {12, "1818989403545856475830078125"}, // * 549755813888 - {13, "9094947017729282379150390625"}, // * 1099511627776 - {13, "45474735088646411895751953125"}, // * 2199023255552 - {13, "227373675443232059478759765625"}, // * 4398046511104 - {13, "1136868377216160297393798828125"}, // * 8796093022208 - {14, "5684341886080801486968994140625"}, // * 17592186044416 - {14, "28421709430404007434844970703125"}, // * 35184372088832 - {14, "142108547152020037174224853515625"}, // * 70368744177664 - {15, "710542735760100185871124267578125"}, // * 140737488355328 - {15, "3552713678800500929355621337890625"}, // * 281474976710656 - {15, "17763568394002504646778106689453125"}, // * 562949953421312 - {16, "88817841970012523233890533447265625"}, // * 1125899906842624 - {16, "444089209850062616169452667236328125"}, // * 2251799813685248 - {16, "2220446049250313080847263336181640625"}, // * 4503599627370496 - {16, "11102230246251565404236316680908203125"}, // * 9007199254740992 - {17, "55511151231257827021181583404541015625"}, // * 18014398509481984 - {17, "277555756156289135105907917022705078125"}, // * 36028797018963968 - {17, "1387778780781445675529539585113525390625"}, // * 72057594037927936 - {18, "6938893903907228377647697925567626953125"}, // * 144115188075855872 - {18, "34694469519536141888238489627838134765625"}, // * 288230376151711744 - {18, "173472347597680709441192448139190673828125"}, // * 576460752303423488 - {19, "867361737988403547205962240695953369140625"}, // * 1152921504606846976 -} - -// Is the leading prefix of b lexicographically less than s? -func prefixIsLessThan(b []byte, s string) bool { - for i := 0; i < len(s); i++ { - if i >= len(b) { - return true - } - if b[i] != s[i] { - return b[i] < s[i] - } - } - return false -} - -// Binary shift left (* 2) by k bits. k <= maxShift to avoid overflow. -func leftShift(a *decimal, k uint) { - delta := leftcheats[k].delta - if prefixIsLessThan(a.d[0:a.nd], leftcheats[k].cutoff) { - delta-- - } - - r := a.nd // read index - w := a.nd + delta // write index - - // Pick up a digit, put down a digit. - var n uint - for r--; r >= 0; r-- { - n += (uint(a.d[r]) - '0') << k - quo := n / 10 - rem := n - 10*quo - w-- - if w < len(a.d) { - a.d[w] = byte(rem + '0') - } else if rem != 0 { - a.trunc = true - } - n = quo - } - - // Put down extra digits. - for n > 0 { - quo := n / 10 - rem := n - 10*quo - w-- - if w < len(a.d) { - a.d[w] = byte(rem + '0') - } else if rem != 0 { - a.trunc = true - } - n = quo - } - - a.nd += delta - if a.nd >= len(a.d) { - a.nd = len(a.d) - } - a.dp += delta - trim(a) -} - -// Binary shift left (k > 0) or right (k < 0). -func (a *decimal) Shift(k int) { - switch { - case a.nd == 0: - // nothing to do: a == 0 - case k > 0: - for k > maxShift { - leftShift(a, maxShift) - k -= maxShift - } - leftShift(a, uint(k)) - case k < 0: - for k < -maxShift { - rightShift(a, maxShift) - k += maxShift - } - rightShift(a, uint(-k)) - } -} - -// If we chop a at nd digits, should we round up? -func shouldRoundUp(a *decimal, nd int) bool { - if nd < 0 || nd >= a.nd { - return false - } - if a.d[nd] == '5' && nd+1 == a.nd { // exactly halfway - round to even - // if we truncated, a little higher than what's recorded - always round up - if a.trunc { - return true - } - return nd > 0 && (a.d[nd-1]-'0')%2 != 0 - } - // not halfway - digit tells all - return a.d[nd] >= '5' -} - -// Round a to nd digits (or fewer). -// If nd is zero, it means we're rounding -// just to the left of the digits, as in -// 0.09 -> 0.1. -func (a *decimal) Round(nd int) { - if nd < 0 || nd >= a.nd { - return - } - if shouldRoundUp(a, nd) { - a.RoundUp(nd) - } else { - a.RoundDown(nd) - } -} - -// Round a down to nd digits (or fewer). -func (a *decimal) RoundDown(nd int) { - if nd < 0 || nd >= a.nd { - return - } - a.nd = nd - trim(a) -} - -// Round a up to nd digits (or fewer). -func (a *decimal) RoundUp(nd int) { - if nd < 0 || nd >= a.nd { - return - } - - // round up - for i := nd - 1; i >= 0; i-- { - c := a.d[i] - if c < '9' { // can stop after this digit - a.d[i]++ - a.nd = i + 1 - return - } - } - - // Number is all 9s. - // Change to single 1 with adjusted decimal point. - a.d[0] = '1' - a.nd = 1 - a.dp++ -} - -// Extract integer part, rounded appropriately. -// No guarantees about overflow. -func (a *decimal) RoundedInteger() uint64 { - if a.dp > 20 { - return 0xFFFFFFFFFFFFFFFF - } - var i int - n := uint64(0) - for i = 0; i < a.dp && i < a.nd; i++ { - n = n*10 + uint64(a.d[i]-'0') - } - for ; i < a.dp; i++ { - n *= 10 - } - if shouldRoundUp(a, a.dp) { - n++ - } - return n -} diff --git a/util/gnolanddev/strconv/decimal_test.gno b/util/gnolanddev/strconv/decimal_test.gno deleted file mode 100644 index b7dcce7c..00000000 --- a/util/gnolanddev/strconv/decimal_test.gno +++ /dev/null @@ -1,126 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package strconv - -import ( - "testing" -) - -type shiftTest struct { - i uint64 - shift int - out string -} - -var shifttests = []shiftTest{ - {0, -100, "0"}, - {0, 100, "0"}, - {1, 100, "1267650600228229401496703205376"}, - {1, -100, - "0.00000000000000000000000000000078886090522101180541" + - "17285652827862296732064351090230047702789306640625", - }, - {12345678, 8, "3160493568"}, - {12345678, -8, "48225.3046875"}, - {195312, 9, "99999744"}, - {1953125, 9, "1000000000"}, -} - -func TestDecimalShift(t *testing.T) { - for i := 0; i < len(shifttests); i++ { - test := &shifttests[i] - d := NewDecimal(test.i) - d.Shift(test.shift) - s := d.String() - if s != test.out { - t.Errorf("Decimal %v << %v = %v, want %v", - test.i, test.shift, s, test.out) - } - } -} - -type roundTest struct { - i uint64 - nd int - down, round, up string - int uint64 -} - -var roundtests = []roundTest{ - {0, 4, "0", "0", "0", 0}, - {12344999, 4, "12340000", "12340000", "12350000", 12340000}, - {12345000, 4, "12340000", "12340000", "12350000", 12340000}, - {12345001, 4, "12340000", "12350000", "12350000", 12350000}, - {23454999, 4, "23450000", "23450000", "23460000", 23450000}, - {23455000, 4, "23450000", "23460000", "23460000", 23460000}, - {23455001, 4, "23450000", "23460000", "23460000", 23460000}, - - {99994999, 4, "99990000", "99990000", "100000000", 99990000}, - {99995000, 4, "99990000", "100000000", "100000000", 100000000}, - {99999999, 4, "99990000", "100000000", "100000000", 100000000}, - - {12994999, 4, "12990000", "12990000", "13000000", 12990000}, - {12995000, 4, "12990000", "13000000", "13000000", 13000000}, - {12999999, 4, "12990000", "13000000", "13000000", 13000000}, -} - -func TestDecimalRound(t *testing.T) { - for i := 0; i < len(roundtests); i++ { - test := &roundtests[i] - d := NewDecimal(test.i) - d.RoundDown(test.nd) - s := d.String() - if s != test.down { - t.Errorf("Decimal %v RoundDown %d = %v, want %v", - test.i, test.nd, s, test.down) - } - d = NewDecimal(test.i) - d.Round(test.nd) - s = d.String() - if s != test.round { - t.Errorf("Decimal %v Round %d = %v, want %v", - test.i, test.nd, s, test.down) - } - d = NewDecimal(test.i) - d.RoundUp(test.nd) - s = d.String() - if s != test.up { - t.Errorf("Decimal %v RoundUp %d = %v, want %v", - test.i, test.nd, s, test.up) - } - } -} - -type roundIntTest struct { - i uint64 - shift int - int uint64 -} - -var roundinttests = []roundIntTest{ - {0, 100, 0}, - {512, -8, 2}, - {513, -8, 2}, - {640, -8, 2}, - {641, -8, 3}, - {384, -8, 2}, - {385, -8, 2}, - {383, -8, 1}, - {1, 100, 1<<64 - 1}, - {1000, 0, 1000}, -} - -func TestDecimalRoundedInteger(t *testing.T) { - for i := 0; i < len(roundinttests); i++ { - test := roundinttests[i] - d := NewDecimal(test.i) - d.Shift(test.shift) - int := d.RoundedInteger() - if int != test.int { - t.Errorf("Decimal %v >> %v RoundedInteger = %v, want %v", - test.i, test.shift, int, test.int) - } - } -} diff --git a/util/gnolanddev/strconv/ftoa.gno b/util/gnolanddev/strconv/ftoa.gno deleted file mode 100644 index da71b1d7..00000000 --- a/util/gnolanddev/strconv/ftoa.gno +++ /dev/null @@ -1,702 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Binary to decimal floating point conversion. -// Algorithm: -// 1) store mantissa in multiprecision decimal -// 2) shift decimal by exponent -// 3) read digits out & format - -package strconv - -import ( - "math" - "math/bits" -) - -// TODO: move elsewhere? -type floatInfo struct { - mantbits uint - expbits uint - bias int -} - -var float32info = floatInfo{23, 8, -127} -var float64info = floatInfo{52, 11, -1023} - -// FormatFloat converts the floating-point number f to a string, -// according to the format fmt and precision prec. It rounds the -// result assuming that the original was obtained from a floating-point -// value of bitSize bits (32 for float32, 64 for float64). -// -// The format fmt is one of -// 'b' (-ddddp±ddd, a binary exponent), -// 'e' (-d.dddde±dd, a decimal exponent), -// 'E' (-d.ddddE±dd, a decimal exponent), -// 'f' (-ddd.dddd, no exponent), -// 'g' ('e' for large exponents, 'f' otherwise), -// 'G' ('E' for large exponents, 'f' otherwise), -// 'x' (-0xd.ddddp±ddd, a hexadecimal fraction and binary exponent), or -// 'X' (-0Xd.ddddP±ddd, a hexadecimal fraction and binary exponent). -// -// The precision prec controls the number of digits (excluding the exponent) -// printed by the 'e', 'E', 'f', 'g', 'G', 'x', and 'X' formats. -// For 'e', 'E', 'f', 'x', and 'X', it is the number of digits after the decimal point. -// For 'g' and 'G' it is the maximum number of significant digits (trailing -// zeros are removed). -// The special precision -1 uses the smallest number of digits -// necessary such that ParseFloat will return f exactly. -func FormatFloat(f float64, fmt byte, prec, bitSize int) string { - return string(genericFtoa(make([]byte, 0, max(prec+4, 24)), f, fmt, prec, bitSize)) -} - -// AppendFloat appends the string form of the floating-point number f, -// as generated by FormatFloat, to dst and returns the extended buffer. -func AppendFloat(dst []byte, f float64, fmt byte, prec, bitSize int) []byte { - return genericFtoa(dst, f, fmt, prec, bitSize) -} - -func genericFtoa(dst []byte, val float64, fmt byte, prec, bitSize int) []byte { - var bits uint64 - var flt *floatInfo - switch bitSize { - case 32: - bits = uint64(math.Float32bits(float32(val))) - flt = &float32info - case 64: - bits = math.Float64bits(val) - flt = &float64info - default: - panic("strconv: illegal AppendFloat/FormatFloat bitSize") - } - - neg := bits>>(flt.expbits+flt.mantbits) != 0 - exp := int(bits>>flt.mantbits) & (1< digs.nd && digs.nd >= digs.dp { - eprec = digs.nd - } - // %e is used if the exponent from the conversion - // is less than -4 or greater than or equal to the precision. - // if precision was the shortest possible, use precision 6 for this decision. - if shortest { - eprec = 6 - } - exp := digs.dp - 1 - if exp < -4 || exp >= eprec { - if prec > digs.nd { - prec = digs.nd - } - return fmtE(dst, neg, digs, prec-1, fmt+'e'-'g') - } - if prec > digs.dp { - prec = digs.nd - } - return fmtF(dst, neg, digs, max(prec-digs.dp, 0)) - } - - // unknown format - return append(dst, byte('%'), fmt) -} - -// roundShortest rounds d (= mant * 2^exp) to the shortest number of digits -// that will let the original floating point value be precisely reconstructed. -func roundShortest(d *decimal, mant uint64, exp int, flt *floatInfo) { - // If mantissa is zero, the number is zero; stop now. - if mant == 0 { - d.nd = 0 - return - } - - // Compute upper and lower such that any decimal number - // between upper and lower (possibly inclusive) - // will round to the original floating point number. - - // We may see at once that the number is already shortest. - // - // Suppose d is not denormal, so that 2^exp <= d < 10^dp. - // The closest shorter number is at least 10^(dp-nd) away. - // The lower/upper bounds computed below are at distance - // at most 2^(exp-mantbits). - // - // So the number is already shortest if 10^(dp-nd) > 2^(exp-mantbits), - // or equivalently log2(10)*(dp-nd) > exp-mantbits. - // It is true if 332/100*(dp-nd) >= exp-mantbits (log2(10) > 3.32). - minexp := flt.bias + 1 // minimum possible exponent - if exp > minexp && 332*(d.dp-d.nd) >= 100*(exp-int(flt.mantbits)) { - // The number is already shortest. - return - } - - // d = mant << (exp - mantbits) - // Next highest floating point number is mant+1 << exp-mantbits. - // Our upper bound is halfway between, mant*2+1 << exp-mantbits-1. - upper := new(decimal) - upper.Assign(mant*2 + 1) - upper.Shift(exp - int(flt.mantbits) - 1) - - // d = mant << (exp - mantbits) - // Next lowest floating point number is mant-1 << exp-mantbits, - // unless mant-1 drops the significant bit and exp is not the minimum exp, - // in which case the next lowest is mant*2-1 << exp-mantbits-1. - // Either way, call it mantlo << explo-mantbits. - // Our lower bound is halfway between, mantlo*2+1 << explo-mantbits-1. - var mantlo uint64 - var explo int - if mant > 1<= d.nd { - break - } - li := ui - upper.dp + lower.dp - l := byte('0') // lower digit - if li >= 0 && li < lower.nd { - l = lower.d[li] - } - m := byte('0') // middle digit - if mi >= 0 { - m = d.d[mi] - } - u := byte('0') // upper digit - if ui < upper.nd { - u = upper.d[ui] - } - - // Okay to round down (truncate) if lower has a different digit - // or if lower is inclusive and is exactly the result of rounding - // down (i.e., and we have reached the final digit of lower). - okdown := l != m || inclusive && li+1 == lower.nd - - switch { - case upperdelta == 0 && m+1 < u: - // Example: - // m = 12345xxx - // u = 12347xxx - upperdelta = 2 - case upperdelta == 0 && m != u: - // Example: - // m = 12345xxx - // u = 12346xxx - upperdelta = 1 - case upperdelta == 1 && (m != '9' || u != '0'): - // Example: - // m = 1234598x - // u = 1234600x - upperdelta = 2 - } - // Okay to round up if upper has a different digit and either upper - // is inclusive or upper is bigger than the result of rounding up. - okup := upperdelta > 0 && (inclusive || upperdelta > 1 || ui+1 < upper.nd) - - // If it's okay to do either, then round to the nearest one. - // If it's okay to do only one, do it. - switch { - case okdown && okup: - d.Round(mi + 1) - return - case okdown: - d.RoundDown(mi + 1) - return - case okup: - d.RoundUp(mi + 1) - return - } - } -} - -type decimalSlice struct { - d []byte - nd, dp int -} - -// %e: -d.ddddde±dd -func fmtE(dst []byte, neg bool, d decimalSlice, prec int, fmt byte) []byte { - // sign - if neg { - dst = append(dst, '-') - } - - // first digit - ch := byte('0') - if d.nd != 0 { - ch = d.d[0] - } - dst = append(dst, ch) - - // .moredigits - if prec > 0 { - dst = append(dst, '.') - i := 1 - m := min(d.nd, prec+1) - if i < m { - dst = append(dst, d.d[i:m]...) - i = m - } - for ; i <= prec; i++ { - dst = append(dst, '0') - } - } - - // e± - dst = append(dst, fmt) - exp := d.dp - 1 - if d.nd == 0 { // special case: 0 has exponent 0 - exp = 0 - } - if exp < 0 { - ch = '-' - exp = -exp - } else { - ch = '+' - } - dst = append(dst, ch) - - // dd or ddd - switch { - case exp < 10: - dst = append(dst, byte('0'), byte(exp)+'0') - case exp < 100: - dst = append(dst, byte(exp/10)+'0', byte(exp%10)+'0') - default: - dst = append(dst, byte(exp/100)+'0', byte(exp/10)%10+'0', byte(exp%10)+'0') - } - - return dst -} - -// %f: -ddddddd.ddddd -func fmtF(dst []byte, neg bool, d decimalSlice, prec int) []byte { - // sign - if neg { - dst = append(dst, '-') - } - - // integer, padded with zeros as needed. - if d.dp > 0 { - m := min(d.nd, d.dp) - dst = append(dst, d.d[:m]...) - for ; m < d.dp; m++ { - dst = append(dst, '0') - } - } else { - dst = append(dst, '0') - } - - // fraction - if prec > 0 { - dst = append(dst, '.') - for i := 0; i < prec; i++ { - ch := byte('0') - if j := d.dp + i; 0 <= j && j < d.nd { - ch = d.d[j] - } - dst = append(dst, ch) - } - } - - return dst -} - -// %b: -ddddddddp±ddd -func fmtB(dst []byte, neg bool, mant uint64, exp int, flt *floatInfo) []byte { - // sign - if neg { - dst = append(dst, '-') - } - - // mantissa - dst, _ = formatBits(dst, mant, 10, false, true) - - // p - dst = append(dst, 'p') - - // ±exponent - exp -= int(flt.mantbits) - if exp >= 0 { - dst = append(dst, '+') - } - dst, _ = formatBits(dst, uint64(exp), 10, exp < 0, true) - - return dst -} - -// %x: -0x1.yyyyyyyyp±ddd or -0x0p+0. (y is hex digit, d is decimal digit) -func fmtX(dst []byte, prec int, fmt byte, neg bool, mant uint64, exp int, flt *floatInfo) []byte { - if mant == 0 { - exp = 0 - } - - // Shift digits so leading 1 (if any) is at bit 1<<60. - mant <<= 60 - flt.mantbits - for mant != 0 && mant&(1<<60) == 0 { - mant <<= 1 - exp-- - } - - // Round if requested. - if prec >= 0 && prec < 15 { - shift := uint(prec * 4) - extra := (mant << shift) & (1<<60 - 1) - mant >>= 60 - shift - if extra|(mant&1) > 1<<59 { - mant++ - } - mant <<= 60 - shift - if mant&(1<<61) != 0 { - // Wrapped around. - mant >>= 1 - exp++ - } - } - - hex := lowerhex - if fmt == 'X' { - hex = upperhex - } - - // sign, 0x, leading digit - if neg { - dst = append(dst, '-') - } - dst = append(dst, byte('0'), fmt, '0'+byte((mant>>60)&1)) - - // .fraction - mant <<= 4 // remove leading 0 or 1 - if prec < 0 && mant != 0 { - dst = append(dst, '.') - for mant != 0 { - dst = append(dst, hex[(mant>>60)&15]) - mant <<= 4 - } - } else if prec > 0 { - dst = append(dst, '.') - for i := 0; i < prec; i++ { - dst = append(dst, hex[(mant>>60)&15]) - mant <<= 4 - } - } - - // p± - ch := byte('P') - if fmt == lower(fmt) { - ch = 'p' - } - dst = append(dst, ch) - if exp < 0 { - ch = '-' - exp = -exp - } else { - ch = '+' - } - dst = append(dst, ch) - - // dd or ddd or dddd - switch { - case exp < 100: - dst = append(dst, byte(exp/10)+'0', byte(exp%10)+'0') - case exp < 1000: - dst = append(dst, byte(exp/100)+'0', byte((exp/10)%10)+'0', byte(exp%10)+'0') - default: - dst = append(dst, byte(exp/1000)+'0', byte(exp/100)%10+'0', byte((exp/10)%10)+'0', byte(exp%10)+'0') - } - - return dst -} - -func min(a, b int) int { - if a < b { - return a - } - return b -} - -func max(a, b int) int { - if a > b { - return a - } - return b -} - -// formatBits computes the string representation of u in the given base. -// If neg is set, u is treated as negative int64 value. If append_ is -// set, the string is appended to dst and the resulting byte slice is -// returned as the first result value; otherwise the string is returned -// as the second result value. -func formatBits(dst []byte, u uint64, base int, neg, append_ bool) (d []byte, s string) { - if base < 2 || base > len(digits) { - panic("strconv: illegal AppendInt/FormatInt base") - } - // 2 <= base && base <= len(digits) - - var a [64 + 1]byte // +1 for sign of 64bit value in base 2 - i := len(a) - - if neg { - u = -u - } - - // convert bits - // We use uint values where we can because those will - // fit into a single register even on a 32bit machine. - if base == 10 { - // common case: use constants for / because - // the compiler can optimize it into a multiply+shift - - // u guaranteed to fit into a uint - us := uint(u) - for us >= 100 { - is := us % 100 * 2 - us /= 100 - i -= 2 - a[i+1] = smallsString[is+1] - a[i+0] = smallsString[is+0] - } - - // us < 100 - is := us * 2 - i-- - a[i] = smallsString[is+1] - if us >= 10 { - i-- - a[i] = smallsString[is] - } - - } else if isPowerOfTwo(base) { - // Use shifts and masks instead of / and %. - // Base is a power of 2 and 2 <= base <= len(digits) where len(digits) is 36. - // The largest power of 2 below or equal to 36 is 32, which is 1 << 5; - // i.e., the largest possible shift count is 5. By &-ind that value with - // the constant 7 we tell the compiler that the shift count is always - // less than 8 which is smaller than any register width. This allows - // the compiler to generate better code for the shift operation. - shift := uint(bits.TrailingZeros(uint(base))) & 7 - b := uint64(base) - m := uint(base) - 1 // == 1<= b { - i-- - a[i] = digits[uint(u)&m] - u >>= shift - } - // u < base - i-- - a[i] = digits[uint(u)] - } else { - // general case - b := uint64(base) - for u >= b { - i-- - // Avoid using r = a%b in addition to q = a/b - // since 64bit division and modulo operations - // are calculated by runtime functions on 32bit machines. - q := u / b - a[i] = digits[uint(u-q*b)] - u = q - } - // u < base - i-- - a[i] = digits[uint(u)] - } - - // add sign, if any - if neg { - i-- - a[i] = '-' - } - - if append_ { - d = append(dst, a[i:]...) - return - } - s = string(a[i:]) - return -} - -const ( - lowerhex = "0123456789abcdef" - upperhex = "0123456789ABCDEF" -) - -func lower(c byte) byte { - return c | ('x' - 'X') -} - -const digits = "0123456789abcdefghijklmnopqrstuvwxyz" -const smallsString = "00010203040506070809" + - "10111213141516171819" + - "20212223242526272829" + - "30313233343536373839" + - "40414243444546474849" + - "50515253545556575859" + - "60616263646566676869" + - "70717273747576777879" + - "80818283848586878889" + - "90919293949596979899" - -func isPowerOfTwo(x int) bool { - return x&(x-1) == 0 -} diff --git a/util/gnolanddev/strconv/ftoa_test.gno b/util/gnolanddev/strconv/ftoa_test.gno deleted file mode 100644 index 7713f0d7..00000000 --- a/util/gnolanddev/strconv/ftoa_test.gno +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package strconv - -import ( - "math" - "math/rand" - "testing" -) - -type ftoaTest struct { - f float64 - fmt byte - prec int - s string -} - -func fdiv(a, b float64) float64 { return a / b } - -const ( - below1e23 = 99999999999999974834176 - above1e23 = 100000000000000008388608 -) - -var ftoatests = []ftoaTest{ - {1, 'e', 5, "1.00000e+00"}, - {1, 'f', 5, "1.00000"}, - {1, 'g', 5, "1"}, - {1, 'g', -1, "1"}, - {1, 'x', -1, "0x1p+00"}, - {1, 'x', 5, "0x1.00000p+00"}, - {20, 'g', -1, "20"}, - {20, 'x', -1, "0x1.4p+04"}, - {1234567.8, 'g', -1, "1.2345678e+06"}, - {1234567.8, 'x', -1, "0x1.2d687cccccccdp+20"}, - {200000, 'g', -1, "200000"}, - {200000, 'x', -1, "0x1.86ap+17"}, - {200000, 'X', -1, "0X1.86AP+17"}, - {2000000, 'g', -1, "2e+06"}, - {1e10, 'g', -1, "1e+10"}, - - // g conversion and zero suppression - {400, 'g', 2, "4e+02"}, - {40, 'g', 2, "40"}, - {4, 'g', 2, "4"}, - {.4, 'g', 2, "0.4"}, - {.04, 'g', 2, "0.04"}, - {.004, 'g', 2, "0.004"}, - {.0004, 'g', 2, "0.0004"}, - {.00004, 'g', 2, "4e-05"}, - {.000004, 'g', 2, "4e-06"}, - - {0, 'e', 5, "0.00000e+00"}, - {0, 'f', 5, "0.00000"}, - {0, 'g', 5, "0"}, - {0, 'g', -1, "0"}, - {0, 'x', 5, "0x0.00000p+00"}, - - {-1, 'e', 5, "-1.00000e+00"}, - {-1, 'f', 5, "-1.00000"}, - {-1, 'g', 5, "-1"}, - {-1, 'g', -1, "-1"}, - - {12, 'e', 5, "1.20000e+01"}, - {12, 'f', 5, "12.00000"}, - {12, 'g', 5, "12"}, - {12, 'g', -1, "12"}, - - {123456700, 'e', 5, "1.23457e+08"}, - {123456700, 'f', 5, "123456700.00000"}, - {123456700, 'g', 5, "1.2346e+08"}, - {123456700, 'g', -1, "1.234567e+08"}, - - {1.2345e6, 'e', 5, "1.23450e+06"}, - {1.2345e6, 'f', 5, "1234500.00000"}, - {1.2345e6, 'g', 5, "1.2345e+06"}, - - // Round to even - {1.2345e6, 'e', 3, "1.234e+06"}, - {1.2355e6, 'e', 3, "1.236e+06"}, - {1.2345, 'f', 3, "1.234"}, - {1.2355, 'f', 3, "1.236"}, - {1234567890123456.5, 'e', 15, "1.234567890123456e+15"}, - {1234567890123457.5, 'e', 15, "1.234567890123458e+15"}, - {108678236358137.625, 'g', -1, "1.0867823635813762e+14"}, - - {1e23, 'e', 17, "9.99999999999999916e+22"}, - {1e23, 'f', 17, "99999999999999991611392.00000000000000000"}, - {1e23, 'g', 17, "9.9999999999999992e+22"}, - - {1e23, 'e', -1, "1e+23"}, - {1e23, 'f', -1, "100000000000000000000000"}, - {1e23, 'g', -1, "1e+23"}, - - {below1e23, 'e', 17, "9.99999999999999748e+22"}, - {below1e23, 'f', 17, "99999999999999974834176.00000000000000000"}, - {below1e23, 'g', 17, "9.9999999999999975e+22"}, - - {below1e23, 'e', -1, "9.999999999999997e+22"}, - {below1e23, 'f', -1, "99999999999999970000000"}, - {below1e23, 'g', -1, "9.999999999999997e+22"}, - - {above1e23, 'e', 17, "1.00000000000000008e+23"}, - {above1e23, 'f', 17, "100000000000000008388608.00000000000000000"}, - {above1e23, 'g', 17, "1.0000000000000001e+23"}, - - {above1e23, 'e', -1, "1.0000000000000001e+23"}, - {above1e23, 'f', -1, "100000000000000010000000"}, - {above1e23, 'g', -1, "1.0000000000000001e+23"}, - - {fdiv(5e-304, 1e20), 'g', -1, "5e-324"}, // avoid constant arithmetic - {fdiv(-5e-304, 1e20), 'g', -1, "-5e-324"}, // avoid constant arithmetic - - {32, 'g', -1, "32"}, - {32, 'g', 0, "3e+01"}, - - {100, 'x', -1, "0x1.9p+06"}, - {100, 'y', -1, "%y"}, - - {math.NaN(), 'g', -1, "NaN"}, - {-math.NaN(), 'g', -1, "NaN"}, - {math.Inf(0), 'g', -1, "+Inf"}, - {math.Inf(-1), 'g', -1, "-Inf"}, - {-math.Inf(0), 'g', -1, "-Inf"}, - - {-1, 'b', -1, "-4503599627370496p-52"}, - - // fixed bugs - {0.9, 'f', 1, "0.9"}, - {0.09, 'f', 1, "0.1"}, - {0.0999, 'f', 1, "0.1"}, - {0.05, 'f', 1, "0.1"}, - {0.05, 'f', 0, "0"}, - {0.5, 'f', 1, "0.5"}, - {0.5, 'f', 0, "0"}, - {1.5, 'f', 0, "2"}, - - // https://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308/ - {2.2250738585072012e-308, 'g', -1, "2.2250738585072014e-308"}, - // https://www.exploringbinary.com/php-hangs-on-numeric-value-2-2250738585072011e-308/ - {2.2250738585072011e-308, 'g', -1, "2.225073858507201e-308"}, - - // Issue 2625. - {383260575764816448, 'f', 0, "383260575764816448"}, - {383260575764816448, 'g', -1, "3.8326057576481645e+17"}, - - // Issue 29491. - {498484681984085570, 'f', -1, "498484681984085570"}, - {-5.8339553793802237e+23, 'g', -1, "-5.8339553793802237e+23"}, - - // Issue 52187 - {123.45, '?', 0, "%?"}, - {123.45, '?', 1, "%?"}, - {123.45, '?', -1, "%?"}, - - // rounding - {2.275555555555555, 'x', -1, "0x1.23456789abcdep+01"}, - {2.275555555555555, 'x', 0, "0x1p+01"}, - {2.275555555555555, 'x', 2, "0x1.23p+01"}, - {2.275555555555555, 'x', 16, "0x1.23456789abcde000p+01"}, - {2.275555555555555, 'x', 21, "0x1.23456789abcde00000000p+01"}, - {2.2755555510520935, 'x', -1, "0x1.2345678p+01"}, - {2.2755555510520935, 'x', 6, "0x1.234568p+01"}, - {2.275555431842804, 'x', -1, "0x1.2345668p+01"}, - {2.275555431842804, 'x', 6, "0x1.234566p+01"}, - {3.999969482421875, 'x', -1, "0x1.ffffp+01"}, - {3.999969482421875, 'x', 4, "0x1.ffffp+01"}, - {3.999969482421875, 'x', 3, "0x1.000p+02"}, - {3.999969482421875, 'x', 2, "0x1.00p+02"}, - {3.999969482421875, 'x', 1, "0x1.0p+02"}, - {3.999969482421875, 'x', 0, "0x1p+02"}, -} - -func TestFtoa(t *testing.T) { - for i := 0; i < len(ftoatests); i++ { - test := &ftoatests[i] - s := FormatFloat(test.f, test.fmt, test.prec, 64) - if s != test.s { - t.Error("testN=64", test.f, string(test.fmt), test.prec, "want", test.s, "got", s) - } - x := AppendFloat([]byte("abc"), test.f, test.fmt, test.prec, 64) - if string(x) != "abc"+test.s { - t.Error("AppendFloat testN=64", test.f, string(test.fmt), test.prec, "want", "abc"+test.s, "got", string(x)) - } - if float64(float32(test.f)) == test.f && test.fmt != 'b' { - s := FormatFloat(test.f, test.fmt, test.prec, 32) - if s != test.s { - t.Error("testN=32", test.f, string(test.fmt), test.prec, "want", test.s, "got", s) - } - x := AppendFloat([]byte("abc"), test.f, test.fmt, test.prec, 32) - if string(x) != "abc"+test.s { - t.Error("AppendFloat testN=32", test.f, string(test.fmt), test.prec, "want", "abc"+test.s, "got", string(x)) - } - } - } -} - -func TestFormatFloatInvalidBitSize(t *testing.T) { - defer func() { - if r := recover(); r == nil { - t.Fatalf("expected panic due to invalid bitSize") - } - }() - _ = FormatFloat(3.14, 'g', -1, 100) -} - -var ftoaBenches = []struct { - name string - float float64 - fmt byte - prec int - bitSize int -}{ - {"Decimal", 33909, 'g', -1, 64}, - {"Float", 339.7784, 'g', -1, 64}, - {"Exp", -5.09e75, 'g', -1, 64}, - {"NegExp", -5.11e-95, 'g', -1, 64}, - {"LongExp", 1.234567890123456e-78, 'g', -1, 64}, - - {"Big", 123456789123456789123456789, 'g', -1, 64}, - {"BinaryExp", -1, 'b', -1, 64}, - - {"32Integer", 33909, 'g', -1, 32}, - {"32ExactFraction", 3.375, 'g', -1, 32}, - {"32Point", 339.7784, 'g', -1, 32}, - {"32Exp", -5.09e25, 'g', -1, 32}, - {"32NegExp", -5.11e-25, 'g', -1, 32}, - {"32Shortest", 1.234567e-8, 'g', -1, 32}, - {"32Fixed8Hard", math.Ldexp(15961084, -125), 'e', 8, 32}, - {"32Fixed9Hard", math.Ldexp(14855922, -83), 'e', 9, 32}, - - {"64Fixed1", 123456, 'e', 3, 64}, - {"64Fixed2", 123.456, 'e', 3, 64}, - {"64Fixed3", 1.23456e+78, 'e', 3, 64}, - {"64Fixed4", 1.23456e-78, 'e', 3, 64}, - {"64Fixed12", 1.23456e-78, 'e', 12, 64}, - {"64Fixed16", 1.23456e-78, 'e', 16, 64}, - // From testdata/testfp.txt - {"64Fixed12Hard", math.Ldexp(6965949469487146, -249), 'e', 12, 64}, - {"64Fixed17Hard", math.Ldexp(8887055249355788, 665), 'e', 17, 64}, - {"64Fixed18Hard", math.Ldexp(6994187472632449, 690), 'e', 18, 64}, - - // Trigger slow path (see issue #15672). - // The shortest is: 8.034137530808823e+43 - {"Slowpath64", 8.03413753080882349e+43, 'e', -1, 64}, - // This denormal is pathological because the lower/upper - // halfways to neighboring floats are: - // 622666234635.321003e-320 ~= 622666234635.321e-320 - // 622666234635.321497e-320 ~= 622666234635.3215e-320 - // making it hard to find the 3rd digit - {"SlowpathDenormal64", 622666234635.3213e-320, 'e', -1, 64}, -} - -func BenchmarkFormatFloat(b *testing.B) { - for _, c := range ftoaBenches { - b.Run(c.name, func(b *testing.B) { - for i := 0; i < b.N; i++ { - FormatFloat(c.float, c.fmt, c.prec, c.bitSize) - } - }) - } -} - -func BenchmarkAppendFloat(b *testing.B) { - dst := make([]byte, 30) - for _, c := range ftoaBenches { - b.Run(c.name, func(b *testing.B) { - for i := 0; i < b.N; i++ { - AppendFloat(dst[:0], c.float, c.fmt, c.prec, c.bitSize) - } - }) - } -} diff --git a/util/gnolanddev/strconv/ftoaryu.gno b/util/gnolanddev/strconv/ftoaryu.gno deleted file mode 100644 index 7b965621..00000000 --- a/util/gnolanddev/strconv/ftoaryu.gno +++ /dev/null @@ -1,1280 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package strconv - -import ( - "math/bits" -) - -// binary to decimal conversion using the Ryū algorithm. -// -// See Ulf Adams, "Ryū: Fast Float-to-String Conversion" (doi:10.1145/3192366.3192369) -// -// Fixed precision formatting is a variant of the original paper's -// algorithm, where a single multiplication by 10^k is required, -// sharing the same rounding guarantees. - -// ryuFtoaFixed32 formats mant*(2^exp) with prec decimal digits. -func ryuFtoaFixed32(d *decimalSlice, mant uint32, exp int, prec int) { - if prec < 0 { - panic("ryuFtoaFixed32 called with negative prec") - } - if prec > 9 { - panic("ryuFtoaFixed32 called with prec > 9") - } - // Zero input. - if mant == 0 { - d.nd, d.dp = 0, 0 - return - } - // Renormalize to a 25-bit mantissa. - e2 := exp - if b := bits.Len32(mant); b < 25 { - mant <<= uint(25 - b) - e2 += b - 25 - } - // Choose an exponent such that rounded mant*(2^e2)*(10^q) has - // at least prec decimal digits, i.e - // mant*(2^e2)*(10^q) >= 10^(prec-1) - // Because mant >= 2^24, it is enough to choose: - // 2^(e2+24) >= 10^(-q+prec-1) - // or q = -mulByLog2Log10(e2+24) + prec - 1 - q := -mulByLog2Log10(e2+24) + prec - 1 - - // Now compute mant*(2^e2)*(10^q). - // Is it an exact computation? - // Only small positive powers of 10 are exact (5^28 has 66 bits). - exact := q <= 27 && q >= 0 - - di, dexp2, d0 := mult64bitPow10(mant, e2, q) - if dexp2 >= 0 { - panic("not enough significant bits after mult64bitPow10") - } - // As a special case, computation might still be exact, if exponent - // was negative and if it amounts to computing an exact division. - // In that case, we ignore all lower bits. - // Note that division by 10^11 cannot be exact as 5^11 has 26 bits. - if q < 0 && q >= -10 && divisibleByPower5(uint64(mant), -q) { - exact = true - d0 = true - } - // Remove extra lower bits and keep rounding info. - extra := uint(-dexp2) - var extraMask uint32 = 1<>extra, di&extraMask - roundUp := false - if exact { - // If we computed an exact product, d + 1/2 - // should round to d+1 if 'd' is odd. - roundUp = dfrac > 1<<(extra-1) || - (dfrac == 1<<(extra-1) && !d0) || - (dfrac == 1<<(extra-1) && d0 && di&1 == 1) - } else { - // otherwise, d+1/2 always rounds up because - // we truncated below. - roundUp = dfrac>>(extra-1) == 1 - } - if dfrac != 0 { - d0 = false - } - // Proceed to the requested number of digits - formatDecimal(d, uint64(di), !d0, roundUp, prec) - // Adjust exponent - d.dp -= q -} - -// ryuFtoaFixed64 formats mant*(2^exp) with prec decimal digits. -func ryuFtoaFixed64(d *decimalSlice, mant uint64, exp int, prec int) { - if prec > 18 { - panic("ryuFtoaFixed64 called with prec > 18") - } - // Zero input. - if mant == 0 { - d.nd, d.dp = 0, 0 - return - } - // Renormalize to a 55-bit mantissa. - e2 := exp - if b := bits.Len64(mant); b < 55 { - mant = mant << uint(55-b) - e2 += b - 55 - } - // Choose an exponent such that rounded mant*(2^e2)*(10^q) has - // at least prec decimal digits, i.e - // mant*(2^e2)*(10^q) >= 10^(prec-1) - // Because mant >= 2^54, it is enough to choose: - // 2^(e2+54) >= 10^(-q+prec-1) - // or q = -mulByLog2Log10(e2+54) + prec - 1 - // - // The minimal required exponent is -mulByLog2Log10(1025)+18 = -291 - // The maximal required exponent is mulByLog2Log10(1074)+18 = 342 - q := -mulByLog2Log10(e2+54) + prec - 1 - - // Now compute mant*(2^e2)*(10^q). - // Is it an exact computation? - // Only small positive powers of 10 are exact (5^55 has 128 bits). - exact := q <= 55 && q >= 0 - - di, dexp2, d0 := mult128bitPow10(mant, e2, q) - if dexp2 >= 0 { - panic("not enough significant bits after mult128bitPow10") - } - // As a special case, computation might still be exact, if exponent - // was negative and if it amounts to computing an exact division. - // In that case, we ignore all lower bits. - // Note that division by 10^23 cannot be exact as 5^23 has 54 bits. - if q < 0 && q >= -22 && divisibleByPower5(mant, -q) { - exact = true - d0 = true - } - // Remove extra lower bits and keep rounding info. - extra := uint(-dexp2) - var extraMask uint64 = 1<>extra, di&extraMask - roundUp := false - if exact { - // If we computed an exact product, d + 1/2 - // should round to d+1 if 'd' is odd. - roundUp = dfrac > 1<<(extra-1) || - (dfrac == 1<<(extra-1) && !d0) || - (dfrac == 1<<(extra-1) && d0 && di&1 == 1) - } else { - // otherwise, d+1/2 always rounds up because - // we truncated below. - roundUp = dfrac>>(extra-1) == 1 - } - if dfrac != 0 { - d0 = false - } - // Proceed to the requested number of digits - formatDecimal(d, di, !d0, roundUp, prec) - // Adjust exponent - d.dp -= q -} - -var uint64pow10 = [...]uint64{ - 1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, - 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, -} - -// formatDecimal fills d with at most prec decimal digits -// of mantissa m. The boolean trunc indicates whether m -// is truncated compared to the original number being formatted. -func formatDecimal(d *decimalSlice, m uint64, trunc bool, roundUp bool, prec int) { - max := uint64pow10[prec] - trimmed := 0 - for m >= max { - a, b := m/10, m%10 - m = a - trimmed++ - if b > 5 { - roundUp = true - } else if b < 5 { - roundUp = false - } else { // b == 5 - // round up if there are trailing digits, - // or if the new value of m is odd (round-to-even convention) - roundUp = trunc || m&1 == 1 - } - if b != 0 { - trunc = true - } - } - if roundUp { - m++ - } - if m >= max { - // Happens if di was originally 99999....xx - m /= 10 - trimmed++ - } - // render digits (similar to formatBits) - n := uint(prec) - d.nd = prec - v := m - for v >= 100 { - var v1, v2 uint64 - if v>>32 == 0 { - v1, v2 = uint64(uint32(v)/100), uint64(uint32(v)%100) - } else { - v1, v2 = v/100, v%100 - } - n -= 2 - d.d[n+1] = smallsString[2*v2+1] - d.d[n+0] = smallsString[2*v2+0] - v = v1 - } - if v > 0 { - n-- - d.d[n] = smallsString[2*v+1] - } - if v >= 10 { - n-- - d.d[n] = smallsString[2*v] - } - for d.d[d.nd-1] == '0' { - d.nd-- - trimmed++ - } - d.dp = d.nd + trimmed -} - -// ryuFtoaShortest formats mant*2^exp with prec decimal digits. -func ryuFtoaShortest(d *decimalSlice, mant uint64, exp int, flt *floatInfo) { - if mant == 0 { - d.nd, d.dp = 0, 0 - return - } - // If input is an exact integer with fewer bits than the mantissa, - // the previous and next integer are not admissible representations. - if exp <= 0 && bits.TrailingZeros64(mant) >= -exp { - mant >>= uint(-exp) - ryuDigits(d, mant, mant, mant, true, false) - return - } - ml, mc, mu, e2 := computeBounds(mant, exp, flt) - if e2 == 0 { - ryuDigits(d, ml, mc, mu, true, false) - return - } - // Find 10^q *larger* than 2^-e2 - q := mulByLog2Log10(-e2) + 1 - - // We are going to multiply by 10^q using 128-bit arithmetic. - // The exponent is the same for all 3 numbers. - var dl, dc, du uint64 - var dl0, dc0, du0 bool - if flt == &float32info { - var dl32, dc32, du32 uint32 - dl32, _, dl0 = mult64bitPow10(uint32(ml), e2, q) - dc32, _, dc0 = mult64bitPow10(uint32(mc), e2, q) - du32, e2, du0 = mult64bitPow10(uint32(mu), e2, q) - dl, dc, du = uint64(dl32), uint64(dc32), uint64(du32) - } else { - dl, _, dl0 = mult128bitPow10(ml, e2, q) - dc, _, dc0 = mult128bitPow10(mc, e2, q) - du, e2, du0 = mult128bitPow10(mu, e2, q) - } - if e2 >= 0 { - panic("not enough significant bits after mult128bitPow10") - } - // Is it an exact computation? - if q > 55 { - // Large positive powers of ten are not exact - dl0, dc0, du0 = false, false, false - } - if q < 0 && q >= -24 { - // Division by a power of ten may be exact. - // (note that 5^25 is a 59-bit number so division by 5^25 is never exact). - if divisibleByPower5(ml, -q) { - dl0 = true - } - if divisibleByPower5(mc, -q) { - dc0 = true - } - if divisibleByPower5(mu, -q) { - du0 = true - } - } - // Express the results (dl, dc, du)*2^e2 as integers. - // Extra bits must be removed and rounding hints computed. - extra := uint(-e2) - var extraMask uint64 = 1<>extra, dl&extraMask - dc, fracc := dc>>extra, dc&extraMask - du, fracu := du>>extra, du&extraMask - // Is it allowed to use 'du' as a result? - // It is always allowed when it is truncated, but also - // if it is exact and the original binary mantissa is even - // When disallowed, we can subtract 1. - uok := !du0 || fracu > 0 - if du0 && fracu == 0 { - uok = mant&1 == 0 - } - if !uok { - du-- - } - // Is 'dc' the correctly rounded base 10 mantissa? - // The correct rounding might be dc+1 - cup := false // don't round up. - if dc0 { - // If we computed an exact product, the half integer - // should round to next (even) integer if 'dc' is odd. - cup = fracc > 1<<(extra-1) || - (fracc == 1<<(extra-1) && dc&1 == 1) - } else { - // otherwise, the result is a lower truncation of the ideal - // result. - cup = fracc>>(extra-1) == 1 - } - // Is 'dl' an allowed representation? - // Only if it is an exact value, and if the original binary mantissa - // was even. - lok := dl0 && fracl == 0 && (mant&1 == 0) - if !lok { - dl++ - } - // We need to remember whether the trimmed digits of 'dc' are zero. - c0 := dc0 && fracc == 0 - // render digits - ryuDigits(d, dl, dc, du, c0, cup) - d.dp -= q -} - -// mulByLog2Log10 returns math.Floor(x * log(2)/log(10)) for an integer x in -// the range -1600 <= x && x <= +1600. -// -// The range restriction lets us work in faster integer arithmetic instead of -// slower floating point arithmetic. Correctness is verified by unit tests. -func mulByLog2Log10(x int) int { - // log(2)/log(10) ≈ 0.30102999566 ≈ 78913 / 2^18 - return (x * 78913) >> 18 -} - -// mulByLog10Log2 returns math.Floor(x * log(10)/log(2)) for an integer x in -// the range -500 <= x && x <= +500. -// -// The range restriction lets us work in faster integer arithmetic instead of -// slower floating point arithmetic. Correctness is verified by unit tests. -func mulByLog10Log2(x int) int { - // log(10)/log(2) ≈ 3.32192809489 ≈ 108853 / 2^15 - return (x * 108853) >> 15 -} - -// computeBounds returns a floating-point vector (l, c, u)×2^e2 -// where the mantissas are 55-bit (or 26-bit) integers, describing the interval -// represented by the input float64 or float32. -func computeBounds(mant uint64, exp int, flt *floatInfo) (lower, central, upper uint64, e2 int) { - if mant != 1< 5e8) || (clo == 5e8 && cup) - ryuDigits32(d, lhi, chi, uhi, c0, cup, 8) - d.dp += 9 - } else { - d.nd = 0 - // emit high part - n := uint(9) - for v := chi; v > 0; { - v1, v2 := v/10, v%10 - v = v1 - n-- - d.d[n] = byte(v2 + '0') - } - d.d = d.d[n:] - d.nd = int(9 - n) - // emit low part - ryuDigits32(d, llo, clo, ulo, - c0, cup, d.nd+8) - } - // trim trailing zeros - for d.nd > 0 && d.d[d.nd-1] == '0' { - d.nd-- - } - // trim initial zeros - for d.nd > 0 && d.d[0] == '0' { - d.nd-- - d.dp-- - d.d = d.d[1:] - } -} - -// ryuDigits32 emits decimal digits for a number less than 1e9. -func ryuDigits32(d *decimalSlice, lower, central, upper uint32, - c0, cup bool, endindex int) { - if upper == 0 { - d.dp = endindex + 1 - return - } - trimmed := 0 - // Remember last trimmed digit to check for round-up. - // c0 will be used to remember zeroness of following digits. - cNextDigit := 0 - for upper > 0 { - // Repeatedly compute: - // l = Ceil(lower / 10^k) - // c = Round(central / 10^k) - // u = Floor(upper / 10^k) - // and stop when c goes out of the (l, u) interval. - l := (lower + 9) / 10 - c, cdigit := central/10, central%10 - u := upper / 10 - if l > u { - // don't trim the last digit as it is forbidden to go below l - // other, trim and exit now. - break - } - // Check that we didn't cross the lower boundary. - // The case where l < u but c == l-1 is essentially impossible, - // but may happen if: - // lower = ..11 - // central = ..19 - // upper = ..31 - // and means that 'central' is very close but less than - // an integer ending with many zeros, and usually - // the "round-up" logic hides the problem. - if l == c+1 && c < u { - c++ - cdigit = 0 - cup = false - } - trimmed++ - // Remember trimmed digits of c - c0 = c0 && cNextDigit == 0 - cNextDigit = int(cdigit) - lower, central, upper = l, c, u - } - // should we round up? - if trimmed > 0 { - cup = cNextDigit > 5 || - (cNextDigit == 5 && !c0) || - (cNextDigit == 5 && c0 && central&1 == 1) - } - if central < upper && cup { - central++ - } - // We know where the number ends, fill directly - endindex -= trimmed - v := central - n := endindex - for n > d.nd { - v1, v2 := v/100, v%100 - d.d[n] = smallsString[2*v2+1] - d.d[n-1] = smallsString[2*v2+0] - n -= 2 - v = v1 - } - if n == d.nd { - d.d[n] = byte(v + '0') - } - d.nd = endindex + 1 - d.dp = d.nd + trimmed -} - -// mult64bitPow10 takes a floating-point input with a 25-bit -// mantissa and multiplies it with 10^q. The resulting mantissa -// is m*P >> 57 where P is a 64-bit element of the detailedPowersOfTen tables. -// It is typically 31 or 32-bit wide. -// The returned boolean is true if all trimmed bits were zero. -// -// That is: -// -// m*2^e2 * round(10^q) = resM * 2^resE + ε -// exact = ε == 0 -func mult64bitPow10(m uint32, e2, q int) (resM uint32, resE int, exact bool) { - if q == 0 { - // P == 1<<63 - return m << 6, e2 - 6, true - } - if q < detailedPowersOfTenMinExp10 || detailedPowersOfTenMaxExp10 < q { - // This never happens due to the range of float32/float64 exponent - panic("mult64bitPow10: power of 10 is out of range") - } - pow := detailedPowersOfTen[q-detailedPowersOfTenMinExp10][1] - if q < 0 { - // Inverse powers of ten must be rounded up. - pow += 1 - } - hi, lo := bits.Mul64(uint64(m), pow) - e2 += mulByLog10Log2(q) - 63 + 57 - return uint32(hi<<7 | lo>>57), e2, lo<<7 == 0 -} - -// mult128bitPow10 takes a floating-point input with a 55-bit -// mantissa and multiplies it with 10^q. The resulting mantissa -// is m*P >> 119 where P is a 128-bit element of the detailedPowersOfTen tables. -// It is typically 63 or 64-bit wide. -// The returned boolean is true is all trimmed bits were zero. -// -// That is: -// -// m*2^e2 * round(10^q) = resM * 2^resE + ε -// exact = ε == 0 -func mult128bitPow10(m uint64, e2, q int) (resM uint64, resE int, exact bool) { - if q == 0 { - // P == 1<<127 - return m << 8, e2 - 8, true - } - if q < detailedPowersOfTenMinExp10 || detailedPowersOfTenMaxExp10 < q { - // This never happens due to the range of float32/float64 exponent - panic("mult128bitPow10: power of 10 is out of range") - } - pow := detailedPowersOfTen[q-detailedPowersOfTenMinExp10] - if q < 0 { - // Inverse powers of ten must be rounded up. - pow[0] += 1 - } - e2 += mulByLog10Log2(q) - 127 + 119 - - // long multiplication - l1, l0 := bits.Mul64(m, pow[0]) - h1, h0 := bits.Mul64(m, pow[1]) - mid, carry := bits.Add64(l1, h0, 0) - h1 += carry - return h1<<9 | mid>>55, e2, mid<<9 == 0 && l0 == 0 -} - -func divisibleByPower5(m uint64, k int) bool { - if m == 0 { - return true - } - for i := 0; i < k; i++ { - if m%5 != 0 { - return false - } - m /= 5 - } - return true -} - -// divmod1e9 computes quotient and remainder of division by 1e9, -// avoiding runtime uint64 division on 32-bit platforms. -func divmod1e9(x uint64) (uint32, uint32) { - return uint32(x / 1e9), uint32(x % 1e9) -} - -// detailedPowersOfTen{Min,Max}Exp10 is the power of 10 represented by the -// first and last rows of detailedPowersOfTen. Both bounds are inclusive. -const ( - detailedPowersOfTenMinExp10 = -348 - detailedPowersOfTenMaxExp10 = +347 -) - -// detailedPowersOfTen contains 128-bit mantissa approximations (rounded down) -// to the powers of 10. For example: -// -// - 1e43 ≈ (0xE596B7B0_C643C719 * (2 ** 79)) -// - 1e43 = (0xE596B7B0_C643C719_6D9CCD05_D0000000 * (2 ** 15)) -// -// The mantissas are explicitly listed. The exponents are implied by a linear -// expression with slope 217706.0/65536.0 ≈ log(10)/log(2). -// -// The table was generated by -// https://github.com/google/wuffs/blob/ba3818cb6b473a2ed0b38ecfc07dbbd3a97e8ae7/script/print-mpb-powers-of-10.go -var detailedPowersOfTen = [...][2]uint64{ - {0x1732C869CD60E453, 0xFA8FD5A0081C0288}, // 1e-348 - {0x0E7FBD42205C8EB4, 0x9C99E58405118195}, // 1e-347 - {0x521FAC92A873B261, 0xC3C05EE50655E1FA}, // 1e-346 - {0xE6A797B752909EF9, 0xF4B0769E47EB5A78}, // 1e-345 - {0x9028BED2939A635C, 0x98EE4A22ECF3188B}, // 1e-344 - {0x7432EE873880FC33, 0xBF29DCABA82FDEAE}, // 1e-343 - {0x113FAA2906A13B3F, 0xEEF453D6923BD65A}, // 1e-342 - {0x4AC7CA59A424C507, 0x9558B4661B6565F8}, // 1e-341 - {0x5D79BCF00D2DF649, 0xBAAEE17FA23EBF76}, // 1e-340 - {0xF4D82C2C107973DC, 0xE95A99DF8ACE6F53}, // 1e-339 - {0x79071B9B8A4BE869, 0x91D8A02BB6C10594}, // 1e-338 - {0x9748E2826CDEE284, 0xB64EC836A47146F9}, // 1e-337 - {0xFD1B1B2308169B25, 0xE3E27A444D8D98B7}, // 1e-336 - {0xFE30F0F5E50E20F7, 0x8E6D8C6AB0787F72}, // 1e-335 - {0xBDBD2D335E51A935, 0xB208EF855C969F4F}, // 1e-334 - {0xAD2C788035E61382, 0xDE8B2B66B3BC4723}, // 1e-333 - {0x4C3BCB5021AFCC31, 0x8B16FB203055AC76}, // 1e-332 - {0xDF4ABE242A1BBF3D, 0xADDCB9E83C6B1793}, // 1e-331 - {0xD71D6DAD34A2AF0D, 0xD953E8624B85DD78}, // 1e-330 - {0x8672648C40E5AD68, 0x87D4713D6F33AA6B}, // 1e-329 - {0x680EFDAF511F18C2, 0xA9C98D8CCB009506}, // 1e-328 - {0x0212BD1B2566DEF2, 0xD43BF0EFFDC0BA48}, // 1e-327 - {0x014BB630F7604B57, 0x84A57695FE98746D}, // 1e-326 - {0x419EA3BD35385E2D, 0xA5CED43B7E3E9188}, // 1e-325 - {0x52064CAC828675B9, 0xCF42894A5DCE35EA}, // 1e-324 - {0x7343EFEBD1940993, 0x818995CE7AA0E1B2}, // 1e-323 - {0x1014EBE6C5F90BF8, 0xA1EBFB4219491A1F}, // 1e-322 - {0xD41A26E077774EF6, 0xCA66FA129F9B60A6}, // 1e-321 - {0x8920B098955522B4, 0xFD00B897478238D0}, // 1e-320 - {0x55B46E5F5D5535B0, 0x9E20735E8CB16382}, // 1e-319 - {0xEB2189F734AA831D, 0xC5A890362FDDBC62}, // 1e-318 - {0xA5E9EC7501D523E4, 0xF712B443BBD52B7B}, // 1e-317 - {0x47B233C92125366E, 0x9A6BB0AA55653B2D}, // 1e-316 - {0x999EC0BB696E840A, 0xC1069CD4EABE89F8}, // 1e-315 - {0xC00670EA43CA250D, 0xF148440A256E2C76}, // 1e-314 - {0x380406926A5E5728, 0x96CD2A865764DBCA}, // 1e-313 - {0xC605083704F5ECF2, 0xBC807527ED3E12BC}, // 1e-312 - {0xF7864A44C633682E, 0xEBA09271E88D976B}, // 1e-311 - {0x7AB3EE6AFBE0211D, 0x93445B8731587EA3}, // 1e-310 - {0x5960EA05BAD82964, 0xB8157268FDAE9E4C}, // 1e-309 - {0x6FB92487298E33BD, 0xE61ACF033D1A45DF}, // 1e-308 - {0xA5D3B6D479F8E056, 0x8FD0C16206306BAB}, // 1e-307 - {0x8F48A4899877186C, 0xB3C4F1BA87BC8696}, // 1e-306 - {0x331ACDABFE94DE87, 0xE0B62E2929ABA83C}, // 1e-305 - {0x9FF0C08B7F1D0B14, 0x8C71DCD9BA0B4925}, // 1e-304 - {0x07ECF0AE5EE44DD9, 0xAF8E5410288E1B6F}, // 1e-303 - {0xC9E82CD9F69D6150, 0xDB71E91432B1A24A}, // 1e-302 - {0xBE311C083A225CD2, 0x892731AC9FAF056E}, // 1e-301 - {0x6DBD630A48AAF406, 0xAB70FE17C79AC6CA}, // 1e-300 - {0x092CBBCCDAD5B108, 0xD64D3D9DB981787D}, // 1e-299 - {0x25BBF56008C58EA5, 0x85F0468293F0EB4E}, // 1e-298 - {0xAF2AF2B80AF6F24E, 0xA76C582338ED2621}, // 1e-297 - {0x1AF5AF660DB4AEE1, 0xD1476E2C07286FAA}, // 1e-296 - {0x50D98D9FC890ED4D, 0x82CCA4DB847945CA}, // 1e-295 - {0xE50FF107BAB528A0, 0xA37FCE126597973C}, // 1e-294 - {0x1E53ED49A96272C8, 0xCC5FC196FEFD7D0C}, // 1e-293 - {0x25E8E89C13BB0F7A, 0xFF77B1FCBEBCDC4F}, // 1e-292 - {0x77B191618C54E9AC, 0x9FAACF3DF73609B1}, // 1e-291 - {0xD59DF5B9EF6A2417, 0xC795830D75038C1D}, // 1e-290 - {0x4B0573286B44AD1D, 0xF97AE3D0D2446F25}, // 1e-289 - {0x4EE367F9430AEC32, 0x9BECCE62836AC577}, // 1e-288 - {0x229C41F793CDA73F, 0xC2E801FB244576D5}, // 1e-287 - {0x6B43527578C1110F, 0xF3A20279ED56D48A}, // 1e-286 - {0x830A13896B78AAA9, 0x9845418C345644D6}, // 1e-285 - {0x23CC986BC656D553, 0xBE5691EF416BD60C}, // 1e-284 - {0x2CBFBE86B7EC8AA8, 0xEDEC366B11C6CB8F}, // 1e-283 - {0x7BF7D71432F3D6A9, 0x94B3A202EB1C3F39}, // 1e-282 - {0xDAF5CCD93FB0CC53, 0xB9E08A83A5E34F07}, // 1e-281 - {0xD1B3400F8F9CFF68, 0xE858AD248F5C22C9}, // 1e-280 - {0x23100809B9C21FA1, 0x91376C36D99995BE}, // 1e-279 - {0xABD40A0C2832A78A, 0xB58547448FFFFB2D}, // 1e-278 - {0x16C90C8F323F516C, 0xE2E69915B3FFF9F9}, // 1e-277 - {0xAE3DA7D97F6792E3, 0x8DD01FAD907FFC3B}, // 1e-276 - {0x99CD11CFDF41779C, 0xB1442798F49FFB4A}, // 1e-275 - {0x40405643D711D583, 0xDD95317F31C7FA1D}, // 1e-274 - {0x482835EA666B2572, 0x8A7D3EEF7F1CFC52}, // 1e-273 - {0xDA3243650005EECF, 0xAD1C8EAB5EE43B66}, // 1e-272 - {0x90BED43E40076A82, 0xD863B256369D4A40}, // 1e-271 - {0x5A7744A6E804A291, 0x873E4F75E2224E68}, // 1e-270 - {0x711515D0A205CB36, 0xA90DE3535AAAE202}, // 1e-269 - {0x0D5A5B44CA873E03, 0xD3515C2831559A83}, // 1e-268 - {0xE858790AFE9486C2, 0x8412D9991ED58091}, // 1e-267 - {0x626E974DBE39A872, 0xA5178FFF668AE0B6}, // 1e-266 - {0xFB0A3D212DC8128F, 0xCE5D73FF402D98E3}, // 1e-265 - {0x7CE66634BC9D0B99, 0x80FA687F881C7F8E}, // 1e-264 - {0x1C1FFFC1EBC44E80, 0xA139029F6A239F72}, // 1e-263 - {0xA327FFB266B56220, 0xC987434744AC874E}, // 1e-262 - {0x4BF1FF9F0062BAA8, 0xFBE9141915D7A922}, // 1e-261 - {0x6F773FC3603DB4A9, 0x9D71AC8FADA6C9B5}, // 1e-260 - {0xCB550FB4384D21D3, 0xC4CE17B399107C22}, // 1e-259 - {0x7E2A53A146606A48, 0xF6019DA07F549B2B}, // 1e-258 - {0x2EDA7444CBFC426D, 0x99C102844F94E0FB}, // 1e-257 - {0xFA911155FEFB5308, 0xC0314325637A1939}, // 1e-256 - {0x793555AB7EBA27CA, 0xF03D93EEBC589F88}, // 1e-255 - {0x4BC1558B2F3458DE, 0x96267C7535B763B5}, // 1e-254 - {0x9EB1AAEDFB016F16, 0xBBB01B9283253CA2}, // 1e-253 - {0x465E15A979C1CADC, 0xEA9C227723EE8BCB}, // 1e-252 - {0x0BFACD89EC191EC9, 0x92A1958A7675175F}, // 1e-251 - {0xCEF980EC671F667B, 0xB749FAED14125D36}, // 1e-250 - {0x82B7E12780E7401A, 0xE51C79A85916F484}, // 1e-249 - {0xD1B2ECB8B0908810, 0x8F31CC0937AE58D2}, // 1e-248 - {0x861FA7E6DCB4AA15, 0xB2FE3F0B8599EF07}, // 1e-247 - {0x67A791E093E1D49A, 0xDFBDCECE67006AC9}, // 1e-246 - {0xE0C8BB2C5C6D24E0, 0x8BD6A141006042BD}, // 1e-245 - {0x58FAE9F773886E18, 0xAECC49914078536D}, // 1e-244 - {0xAF39A475506A899E, 0xDA7F5BF590966848}, // 1e-243 - {0x6D8406C952429603, 0x888F99797A5E012D}, // 1e-242 - {0xC8E5087BA6D33B83, 0xAAB37FD7D8F58178}, // 1e-241 - {0xFB1E4A9A90880A64, 0xD5605FCDCF32E1D6}, // 1e-240 - {0x5CF2EEA09A55067F, 0x855C3BE0A17FCD26}, // 1e-239 - {0xF42FAA48C0EA481E, 0xA6B34AD8C9DFC06F}, // 1e-238 - {0xF13B94DAF124DA26, 0xD0601D8EFC57B08B}, // 1e-237 - {0x76C53D08D6B70858, 0x823C12795DB6CE57}, // 1e-236 - {0x54768C4B0C64CA6E, 0xA2CB1717B52481ED}, // 1e-235 - {0xA9942F5DCF7DFD09, 0xCB7DDCDDA26DA268}, // 1e-234 - {0xD3F93B35435D7C4C, 0xFE5D54150B090B02}, // 1e-233 - {0xC47BC5014A1A6DAF, 0x9EFA548D26E5A6E1}, // 1e-232 - {0x359AB6419CA1091B, 0xC6B8E9B0709F109A}, // 1e-231 - {0xC30163D203C94B62, 0xF867241C8CC6D4C0}, // 1e-230 - {0x79E0DE63425DCF1D, 0x9B407691D7FC44F8}, // 1e-229 - {0x985915FC12F542E4, 0xC21094364DFB5636}, // 1e-228 - {0x3E6F5B7B17B2939D, 0xF294B943E17A2BC4}, // 1e-227 - {0xA705992CEECF9C42, 0x979CF3CA6CEC5B5A}, // 1e-226 - {0x50C6FF782A838353, 0xBD8430BD08277231}, // 1e-225 - {0xA4F8BF5635246428, 0xECE53CEC4A314EBD}, // 1e-224 - {0x871B7795E136BE99, 0x940F4613AE5ED136}, // 1e-223 - {0x28E2557B59846E3F, 0xB913179899F68584}, // 1e-222 - {0x331AEADA2FE589CF, 0xE757DD7EC07426E5}, // 1e-221 - {0x3FF0D2C85DEF7621, 0x9096EA6F3848984F}, // 1e-220 - {0x0FED077A756B53A9, 0xB4BCA50B065ABE63}, // 1e-219 - {0xD3E8495912C62894, 0xE1EBCE4DC7F16DFB}, // 1e-218 - {0x64712DD7ABBBD95C, 0x8D3360F09CF6E4BD}, // 1e-217 - {0xBD8D794D96AACFB3, 0xB080392CC4349DEC}, // 1e-216 - {0xECF0D7A0FC5583A0, 0xDCA04777F541C567}, // 1e-215 - {0xF41686C49DB57244, 0x89E42CAAF9491B60}, // 1e-214 - {0x311C2875C522CED5, 0xAC5D37D5B79B6239}, // 1e-213 - {0x7D633293366B828B, 0xD77485CB25823AC7}, // 1e-212 - {0xAE5DFF9C02033197, 0x86A8D39EF77164BC}, // 1e-211 - {0xD9F57F830283FDFC, 0xA8530886B54DBDEB}, // 1e-210 - {0xD072DF63C324FD7B, 0xD267CAA862A12D66}, // 1e-209 - {0x4247CB9E59F71E6D, 0x8380DEA93DA4BC60}, // 1e-208 - {0x52D9BE85F074E608, 0xA46116538D0DEB78}, // 1e-207 - {0x67902E276C921F8B, 0xCD795BE870516656}, // 1e-206 - {0x00BA1CD8A3DB53B6, 0x806BD9714632DFF6}, // 1e-205 - {0x80E8A40ECCD228A4, 0xA086CFCD97BF97F3}, // 1e-204 - {0x6122CD128006B2CD, 0xC8A883C0FDAF7DF0}, // 1e-203 - {0x796B805720085F81, 0xFAD2A4B13D1B5D6C}, // 1e-202 - {0xCBE3303674053BB0, 0x9CC3A6EEC6311A63}, // 1e-201 - {0xBEDBFC4411068A9C, 0xC3F490AA77BD60FC}, // 1e-200 - {0xEE92FB5515482D44, 0xF4F1B4D515ACB93B}, // 1e-199 - {0x751BDD152D4D1C4A, 0x991711052D8BF3C5}, // 1e-198 - {0xD262D45A78A0635D, 0xBF5CD54678EEF0B6}, // 1e-197 - {0x86FB897116C87C34, 0xEF340A98172AACE4}, // 1e-196 - {0xD45D35E6AE3D4DA0, 0x9580869F0E7AAC0E}, // 1e-195 - {0x8974836059CCA109, 0xBAE0A846D2195712}, // 1e-194 - {0x2BD1A438703FC94B, 0xE998D258869FACD7}, // 1e-193 - {0x7B6306A34627DDCF, 0x91FF83775423CC06}, // 1e-192 - {0x1A3BC84C17B1D542, 0xB67F6455292CBF08}, // 1e-191 - {0x20CABA5F1D9E4A93, 0xE41F3D6A7377EECA}, // 1e-190 - {0x547EB47B7282EE9C, 0x8E938662882AF53E}, // 1e-189 - {0xE99E619A4F23AA43, 0xB23867FB2A35B28D}, // 1e-188 - {0x6405FA00E2EC94D4, 0xDEC681F9F4C31F31}, // 1e-187 - {0xDE83BC408DD3DD04, 0x8B3C113C38F9F37E}, // 1e-186 - {0x9624AB50B148D445, 0xAE0B158B4738705E}, // 1e-185 - {0x3BADD624DD9B0957, 0xD98DDAEE19068C76}, // 1e-184 - {0xE54CA5D70A80E5D6, 0x87F8A8D4CFA417C9}, // 1e-183 - {0x5E9FCF4CCD211F4C, 0xA9F6D30A038D1DBC}, // 1e-182 - {0x7647C3200069671F, 0xD47487CC8470652B}, // 1e-181 - {0x29ECD9F40041E073, 0x84C8D4DFD2C63F3B}, // 1e-180 - {0xF468107100525890, 0xA5FB0A17C777CF09}, // 1e-179 - {0x7182148D4066EEB4, 0xCF79CC9DB955C2CC}, // 1e-178 - {0xC6F14CD848405530, 0x81AC1FE293D599BF}, // 1e-177 - {0xB8ADA00E5A506A7C, 0xA21727DB38CB002F}, // 1e-176 - {0xA6D90811F0E4851C, 0xCA9CF1D206FDC03B}, // 1e-175 - {0x908F4A166D1DA663, 0xFD442E4688BD304A}, // 1e-174 - {0x9A598E4E043287FE, 0x9E4A9CEC15763E2E}, // 1e-173 - {0x40EFF1E1853F29FD, 0xC5DD44271AD3CDBA}, // 1e-172 - {0xD12BEE59E68EF47C, 0xF7549530E188C128}, // 1e-171 - {0x82BB74F8301958CE, 0x9A94DD3E8CF578B9}, // 1e-170 - {0xE36A52363C1FAF01, 0xC13A148E3032D6E7}, // 1e-169 - {0xDC44E6C3CB279AC1, 0xF18899B1BC3F8CA1}, // 1e-168 - {0x29AB103A5EF8C0B9, 0x96F5600F15A7B7E5}, // 1e-167 - {0x7415D448F6B6F0E7, 0xBCB2B812DB11A5DE}, // 1e-166 - {0x111B495B3464AD21, 0xEBDF661791D60F56}, // 1e-165 - {0xCAB10DD900BEEC34, 0x936B9FCEBB25C995}, // 1e-164 - {0x3D5D514F40EEA742, 0xB84687C269EF3BFB}, // 1e-163 - {0x0CB4A5A3112A5112, 0xE65829B3046B0AFA}, // 1e-162 - {0x47F0E785EABA72AB, 0x8FF71A0FE2C2E6DC}, // 1e-161 - {0x59ED216765690F56, 0xB3F4E093DB73A093}, // 1e-160 - {0x306869C13EC3532C, 0xE0F218B8D25088B8}, // 1e-159 - {0x1E414218C73A13FB, 0x8C974F7383725573}, // 1e-158 - {0xE5D1929EF90898FA, 0xAFBD2350644EEACF}, // 1e-157 - {0xDF45F746B74ABF39, 0xDBAC6C247D62A583}, // 1e-156 - {0x6B8BBA8C328EB783, 0x894BC396CE5DA772}, // 1e-155 - {0x066EA92F3F326564, 0xAB9EB47C81F5114F}, // 1e-154 - {0xC80A537B0EFEFEBD, 0xD686619BA27255A2}, // 1e-153 - {0xBD06742CE95F5F36, 0x8613FD0145877585}, // 1e-152 - {0x2C48113823B73704, 0xA798FC4196E952E7}, // 1e-151 - {0xF75A15862CA504C5, 0xD17F3B51FCA3A7A0}, // 1e-150 - {0x9A984D73DBE722FB, 0x82EF85133DE648C4}, // 1e-149 - {0xC13E60D0D2E0EBBA, 0xA3AB66580D5FDAF5}, // 1e-148 - {0x318DF905079926A8, 0xCC963FEE10B7D1B3}, // 1e-147 - {0xFDF17746497F7052, 0xFFBBCFE994E5C61F}, // 1e-146 - {0xFEB6EA8BEDEFA633, 0x9FD561F1FD0F9BD3}, // 1e-145 - {0xFE64A52EE96B8FC0, 0xC7CABA6E7C5382C8}, // 1e-144 - {0x3DFDCE7AA3C673B0, 0xF9BD690A1B68637B}, // 1e-143 - {0x06BEA10CA65C084E, 0x9C1661A651213E2D}, // 1e-142 - {0x486E494FCFF30A62, 0xC31BFA0FE5698DB8}, // 1e-141 - {0x5A89DBA3C3EFCCFA, 0xF3E2F893DEC3F126}, // 1e-140 - {0xF89629465A75E01C, 0x986DDB5C6B3A76B7}, // 1e-139 - {0xF6BBB397F1135823, 0xBE89523386091465}, // 1e-138 - {0x746AA07DED582E2C, 0xEE2BA6C0678B597F}, // 1e-137 - {0xA8C2A44EB4571CDC, 0x94DB483840B717EF}, // 1e-136 - {0x92F34D62616CE413, 0xBA121A4650E4DDEB}, // 1e-135 - {0x77B020BAF9C81D17, 0xE896A0D7E51E1566}, // 1e-134 - {0x0ACE1474DC1D122E, 0x915E2486EF32CD60}, // 1e-133 - {0x0D819992132456BA, 0xB5B5ADA8AAFF80B8}, // 1e-132 - {0x10E1FFF697ED6C69, 0xE3231912D5BF60E6}, // 1e-131 - {0xCA8D3FFA1EF463C1, 0x8DF5EFABC5979C8F}, // 1e-130 - {0xBD308FF8A6B17CB2, 0xB1736B96B6FD83B3}, // 1e-129 - {0xAC7CB3F6D05DDBDE, 0xDDD0467C64BCE4A0}, // 1e-128 - {0x6BCDF07A423AA96B, 0x8AA22C0DBEF60EE4}, // 1e-127 - {0x86C16C98D2C953C6, 0xAD4AB7112EB3929D}, // 1e-126 - {0xE871C7BF077BA8B7, 0xD89D64D57A607744}, // 1e-125 - {0x11471CD764AD4972, 0x87625F056C7C4A8B}, // 1e-124 - {0xD598E40D3DD89BCF, 0xA93AF6C6C79B5D2D}, // 1e-123 - {0x4AFF1D108D4EC2C3, 0xD389B47879823479}, // 1e-122 - {0xCEDF722A585139BA, 0x843610CB4BF160CB}, // 1e-121 - {0xC2974EB4EE658828, 0xA54394FE1EEDB8FE}, // 1e-120 - {0x733D226229FEEA32, 0xCE947A3DA6A9273E}, // 1e-119 - {0x0806357D5A3F525F, 0x811CCC668829B887}, // 1e-118 - {0xCA07C2DCB0CF26F7, 0xA163FF802A3426A8}, // 1e-117 - {0xFC89B393DD02F0B5, 0xC9BCFF6034C13052}, // 1e-116 - {0xBBAC2078D443ACE2, 0xFC2C3F3841F17C67}, // 1e-115 - {0xD54B944B84AA4C0D, 0x9D9BA7832936EDC0}, // 1e-114 - {0x0A9E795E65D4DF11, 0xC5029163F384A931}, // 1e-113 - {0x4D4617B5FF4A16D5, 0xF64335BCF065D37D}, // 1e-112 - {0x504BCED1BF8E4E45, 0x99EA0196163FA42E}, // 1e-111 - {0xE45EC2862F71E1D6, 0xC06481FB9BCF8D39}, // 1e-110 - {0x5D767327BB4E5A4C, 0xF07DA27A82C37088}, // 1e-109 - {0x3A6A07F8D510F86F, 0x964E858C91BA2655}, // 1e-108 - {0x890489F70A55368B, 0xBBE226EFB628AFEA}, // 1e-107 - {0x2B45AC74CCEA842E, 0xEADAB0ABA3B2DBE5}, // 1e-106 - {0x3B0B8BC90012929D, 0x92C8AE6B464FC96F}, // 1e-105 - {0x09CE6EBB40173744, 0xB77ADA0617E3BBCB}, // 1e-104 - {0xCC420A6A101D0515, 0xE55990879DDCAABD}, // 1e-103 - {0x9FA946824A12232D, 0x8F57FA54C2A9EAB6}, // 1e-102 - {0x47939822DC96ABF9, 0xB32DF8E9F3546564}, // 1e-101 - {0x59787E2B93BC56F7, 0xDFF9772470297EBD}, // 1e-100 - {0x57EB4EDB3C55B65A, 0x8BFBEA76C619EF36}, // 1e-99 - {0xEDE622920B6B23F1, 0xAEFAE51477A06B03}, // 1e-98 - {0xE95FAB368E45ECED, 0xDAB99E59958885C4}, // 1e-97 - {0x11DBCB0218EBB414, 0x88B402F7FD75539B}, // 1e-96 - {0xD652BDC29F26A119, 0xAAE103B5FCD2A881}, // 1e-95 - {0x4BE76D3346F0495F, 0xD59944A37C0752A2}, // 1e-94 - {0x6F70A4400C562DDB, 0x857FCAE62D8493A5}, // 1e-93 - {0xCB4CCD500F6BB952, 0xA6DFBD9FB8E5B88E}, // 1e-92 - {0x7E2000A41346A7A7, 0xD097AD07A71F26B2}, // 1e-91 - {0x8ED400668C0C28C8, 0x825ECC24C873782F}, // 1e-90 - {0x728900802F0F32FA, 0xA2F67F2DFA90563B}, // 1e-89 - {0x4F2B40A03AD2FFB9, 0xCBB41EF979346BCA}, // 1e-88 - {0xE2F610C84987BFA8, 0xFEA126B7D78186BC}, // 1e-87 - {0x0DD9CA7D2DF4D7C9, 0x9F24B832E6B0F436}, // 1e-86 - {0x91503D1C79720DBB, 0xC6EDE63FA05D3143}, // 1e-85 - {0x75A44C6397CE912A, 0xF8A95FCF88747D94}, // 1e-84 - {0xC986AFBE3EE11ABA, 0x9B69DBE1B548CE7C}, // 1e-83 - {0xFBE85BADCE996168, 0xC24452DA229B021B}, // 1e-82 - {0xFAE27299423FB9C3, 0xF2D56790AB41C2A2}, // 1e-81 - {0xDCCD879FC967D41A, 0x97C560BA6B0919A5}, // 1e-80 - {0x5400E987BBC1C920, 0xBDB6B8E905CB600F}, // 1e-79 - {0x290123E9AAB23B68, 0xED246723473E3813}, // 1e-78 - {0xF9A0B6720AAF6521, 0x9436C0760C86E30B}, // 1e-77 - {0xF808E40E8D5B3E69, 0xB94470938FA89BCE}, // 1e-76 - {0xB60B1D1230B20E04, 0xE7958CB87392C2C2}, // 1e-75 - {0xB1C6F22B5E6F48C2, 0x90BD77F3483BB9B9}, // 1e-74 - {0x1E38AEB6360B1AF3, 0xB4ECD5F01A4AA828}, // 1e-73 - {0x25C6DA63C38DE1B0, 0xE2280B6C20DD5232}, // 1e-72 - {0x579C487E5A38AD0E, 0x8D590723948A535F}, // 1e-71 - {0x2D835A9DF0C6D851, 0xB0AF48EC79ACE837}, // 1e-70 - {0xF8E431456CF88E65, 0xDCDB1B2798182244}, // 1e-69 - {0x1B8E9ECB641B58FF, 0x8A08F0F8BF0F156B}, // 1e-68 - {0xE272467E3D222F3F, 0xAC8B2D36EED2DAC5}, // 1e-67 - {0x5B0ED81DCC6ABB0F, 0xD7ADF884AA879177}, // 1e-66 - {0x98E947129FC2B4E9, 0x86CCBB52EA94BAEA}, // 1e-65 - {0x3F2398D747B36224, 0xA87FEA27A539E9A5}, // 1e-64 - {0x8EEC7F0D19A03AAD, 0xD29FE4B18E88640E}, // 1e-63 - {0x1953CF68300424AC, 0x83A3EEEEF9153E89}, // 1e-62 - {0x5FA8C3423C052DD7, 0xA48CEAAAB75A8E2B}, // 1e-61 - {0x3792F412CB06794D, 0xCDB02555653131B6}, // 1e-60 - {0xE2BBD88BBEE40BD0, 0x808E17555F3EBF11}, // 1e-59 - {0x5B6ACEAEAE9D0EC4, 0xA0B19D2AB70E6ED6}, // 1e-58 - {0xF245825A5A445275, 0xC8DE047564D20A8B}, // 1e-57 - {0xEED6E2F0F0D56712, 0xFB158592BE068D2E}, // 1e-56 - {0x55464DD69685606B, 0x9CED737BB6C4183D}, // 1e-55 - {0xAA97E14C3C26B886, 0xC428D05AA4751E4C}, // 1e-54 - {0xD53DD99F4B3066A8, 0xF53304714D9265DF}, // 1e-53 - {0xE546A8038EFE4029, 0x993FE2C6D07B7FAB}, // 1e-52 - {0xDE98520472BDD033, 0xBF8FDB78849A5F96}, // 1e-51 - {0x963E66858F6D4440, 0xEF73D256A5C0F77C}, // 1e-50 - {0xDDE7001379A44AA8, 0x95A8637627989AAD}, // 1e-49 - {0x5560C018580D5D52, 0xBB127C53B17EC159}, // 1e-48 - {0xAAB8F01E6E10B4A6, 0xE9D71B689DDE71AF}, // 1e-47 - {0xCAB3961304CA70E8, 0x9226712162AB070D}, // 1e-46 - {0x3D607B97C5FD0D22, 0xB6B00D69BB55C8D1}, // 1e-45 - {0x8CB89A7DB77C506A, 0xE45C10C42A2B3B05}, // 1e-44 - {0x77F3608E92ADB242, 0x8EB98A7A9A5B04E3}, // 1e-43 - {0x55F038B237591ED3, 0xB267ED1940F1C61C}, // 1e-42 - {0x6B6C46DEC52F6688, 0xDF01E85F912E37A3}, // 1e-41 - {0x2323AC4B3B3DA015, 0x8B61313BBABCE2C6}, // 1e-40 - {0xABEC975E0A0D081A, 0xAE397D8AA96C1B77}, // 1e-39 - {0x96E7BD358C904A21, 0xD9C7DCED53C72255}, // 1e-38 - {0x7E50D64177DA2E54, 0x881CEA14545C7575}, // 1e-37 - {0xDDE50BD1D5D0B9E9, 0xAA242499697392D2}, // 1e-36 - {0x955E4EC64B44E864, 0xD4AD2DBFC3D07787}, // 1e-35 - {0xBD5AF13BEF0B113E, 0x84EC3C97DA624AB4}, // 1e-34 - {0xECB1AD8AEACDD58E, 0xA6274BBDD0FADD61}, // 1e-33 - {0x67DE18EDA5814AF2, 0xCFB11EAD453994BA}, // 1e-32 - {0x80EACF948770CED7, 0x81CEB32C4B43FCF4}, // 1e-31 - {0xA1258379A94D028D, 0xA2425FF75E14FC31}, // 1e-30 - {0x096EE45813A04330, 0xCAD2F7F5359A3B3E}, // 1e-29 - {0x8BCA9D6E188853FC, 0xFD87B5F28300CA0D}, // 1e-28 - {0x775EA264CF55347D, 0x9E74D1B791E07E48}, // 1e-27 - {0x95364AFE032A819D, 0xC612062576589DDA}, // 1e-26 - {0x3A83DDBD83F52204, 0xF79687AED3EEC551}, // 1e-25 - {0xC4926A9672793542, 0x9ABE14CD44753B52}, // 1e-24 - {0x75B7053C0F178293, 0xC16D9A0095928A27}, // 1e-23 - {0x5324C68B12DD6338, 0xF1C90080BAF72CB1}, // 1e-22 - {0xD3F6FC16EBCA5E03, 0x971DA05074DA7BEE}, // 1e-21 - {0x88F4BB1CA6BCF584, 0xBCE5086492111AEA}, // 1e-20 - {0x2B31E9E3D06C32E5, 0xEC1E4A7DB69561A5}, // 1e-19 - {0x3AFF322E62439FCF, 0x9392EE8E921D5D07}, // 1e-18 - {0x09BEFEB9FAD487C2, 0xB877AA3236A4B449}, // 1e-17 - {0x4C2EBE687989A9B3, 0xE69594BEC44DE15B}, // 1e-16 - {0x0F9D37014BF60A10, 0x901D7CF73AB0ACD9}, // 1e-15 - {0x538484C19EF38C94, 0xB424DC35095CD80F}, // 1e-14 - {0x2865A5F206B06FB9, 0xE12E13424BB40E13}, // 1e-13 - {0xF93F87B7442E45D3, 0x8CBCCC096F5088CB}, // 1e-12 - {0xF78F69A51539D748, 0xAFEBFF0BCB24AAFE}, // 1e-11 - {0xB573440E5A884D1B, 0xDBE6FECEBDEDD5BE}, // 1e-10 - {0x31680A88F8953030, 0x89705F4136B4A597}, // 1e-9 - {0xFDC20D2B36BA7C3D, 0xABCC77118461CEFC}, // 1e-8 - {0x3D32907604691B4C, 0xD6BF94D5E57A42BC}, // 1e-7 - {0xA63F9A49C2C1B10F, 0x8637BD05AF6C69B5}, // 1e-6 - {0x0FCF80DC33721D53, 0xA7C5AC471B478423}, // 1e-5 - {0xD3C36113404EA4A8, 0xD1B71758E219652B}, // 1e-4 - {0x645A1CAC083126E9, 0x83126E978D4FDF3B}, // 1e-3 - {0x3D70A3D70A3D70A3, 0xA3D70A3D70A3D70A}, // 1e-2 - {0xCCCCCCCCCCCCCCCC, 0xCCCCCCCCCCCCCCCC}, // 1e-1 - {0x0000000000000000, 0x8000000000000000}, // 1e0 - {0x0000000000000000, 0xA000000000000000}, // 1e1 - {0x0000000000000000, 0xC800000000000000}, // 1e2 - {0x0000000000000000, 0xFA00000000000000}, // 1e3 - {0x0000000000000000, 0x9C40000000000000}, // 1e4 - {0x0000000000000000, 0xC350000000000000}, // 1e5 - {0x0000000000000000, 0xF424000000000000}, // 1e6 - {0x0000000000000000, 0x9896800000000000}, // 1e7 - {0x0000000000000000, 0xBEBC200000000000}, // 1e8 - {0x0000000000000000, 0xEE6B280000000000}, // 1e9 - {0x0000000000000000, 0x9502F90000000000}, // 1e10 - {0x0000000000000000, 0xBA43B74000000000}, // 1e11 - {0x0000000000000000, 0xE8D4A51000000000}, // 1e12 - {0x0000000000000000, 0x9184E72A00000000}, // 1e13 - {0x0000000000000000, 0xB5E620F480000000}, // 1e14 - {0x0000000000000000, 0xE35FA931A0000000}, // 1e15 - {0x0000000000000000, 0x8E1BC9BF04000000}, // 1e16 - {0x0000000000000000, 0xB1A2BC2EC5000000}, // 1e17 - {0x0000000000000000, 0xDE0B6B3A76400000}, // 1e18 - {0x0000000000000000, 0x8AC7230489E80000}, // 1e19 - {0x0000000000000000, 0xAD78EBC5AC620000}, // 1e20 - {0x0000000000000000, 0xD8D726B7177A8000}, // 1e21 - {0x0000000000000000, 0x878678326EAC9000}, // 1e22 - {0x0000000000000000, 0xA968163F0A57B400}, // 1e23 - {0x0000000000000000, 0xD3C21BCECCEDA100}, // 1e24 - {0x0000000000000000, 0x84595161401484A0}, // 1e25 - {0x0000000000000000, 0xA56FA5B99019A5C8}, // 1e26 - {0x0000000000000000, 0xCECB8F27F4200F3A}, // 1e27 - {0x4000000000000000, 0x813F3978F8940984}, // 1e28 - {0x5000000000000000, 0xA18F07D736B90BE5}, // 1e29 - {0xA400000000000000, 0xC9F2C9CD04674EDE}, // 1e30 - {0x4D00000000000000, 0xFC6F7C4045812296}, // 1e31 - {0xF020000000000000, 0x9DC5ADA82B70B59D}, // 1e32 - {0x6C28000000000000, 0xC5371912364CE305}, // 1e33 - {0xC732000000000000, 0xF684DF56C3E01BC6}, // 1e34 - {0x3C7F400000000000, 0x9A130B963A6C115C}, // 1e35 - {0x4B9F100000000000, 0xC097CE7BC90715B3}, // 1e36 - {0x1E86D40000000000, 0xF0BDC21ABB48DB20}, // 1e37 - {0x1314448000000000, 0x96769950B50D88F4}, // 1e38 - {0x17D955A000000000, 0xBC143FA4E250EB31}, // 1e39 - {0x5DCFAB0800000000, 0xEB194F8E1AE525FD}, // 1e40 - {0x5AA1CAE500000000, 0x92EFD1B8D0CF37BE}, // 1e41 - {0xF14A3D9E40000000, 0xB7ABC627050305AD}, // 1e42 - {0x6D9CCD05D0000000, 0xE596B7B0C643C719}, // 1e43 - {0xE4820023A2000000, 0x8F7E32CE7BEA5C6F}, // 1e44 - {0xDDA2802C8A800000, 0xB35DBF821AE4F38B}, // 1e45 - {0xD50B2037AD200000, 0xE0352F62A19E306E}, // 1e46 - {0x4526F422CC340000, 0x8C213D9DA502DE45}, // 1e47 - {0x9670B12B7F410000, 0xAF298D050E4395D6}, // 1e48 - {0x3C0CDD765F114000, 0xDAF3F04651D47B4C}, // 1e49 - {0xA5880A69FB6AC800, 0x88D8762BF324CD0F}, // 1e50 - {0x8EEA0D047A457A00, 0xAB0E93B6EFEE0053}, // 1e51 - {0x72A4904598D6D880, 0xD5D238A4ABE98068}, // 1e52 - {0x47A6DA2B7F864750, 0x85A36366EB71F041}, // 1e53 - {0x999090B65F67D924, 0xA70C3C40A64E6C51}, // 1e54 - {0xFFF4B4E3F741CF6D, 0xD0CF4B50CFE20765}, // 1e55 - {0xBFF8F10E7A8921A4, 0x82818F1281ED449F}, // 1e56 - {0xAFF72D52192B6A0D, 0xA321F2D7226895C7}, // 1e57 - {0x9BF4F8A69F764490, 0xCBEA6F8CEB02BB39}, // 1e58 - {0x02F236D04753D5B4, 0xFEE50B7025C36A08}, // 1e59 - {0x01D762422C946590, 0x9F4F2726179A2245}, // 1e60 - {0x424D3AD2B7B97EF5, 0xC722F0EF9D80AAD6}, // 1e61 - {0xD2E0898765A7DEB2, 0xF8EBAD2B84E0D58B}, // 1e62 - {0x63CC55F49F88EB2F, 0x9B934C3B330C8577}, // 1e63 - {0x3CBF6B71C76B25FB, 0xC2781F49FFCFA6D5}, // 1e64 - {0x8BEF464E3945EF7A, 0xF316271C7FC3908A}, // 1e65 - {0x97758BF0E3CBB5AC, 0x97EDD871CFDA3A56}, // 1e66 - {0x3D52EEED1CBEA317, 0xBDE94E8E43D0C8EC}, // 1e67 - {0x4CA7AAA863EE4BDD, 0xED63A231D4C4FB27}, // 1e68 - {0x8FE8CAA93E74EF6A, 0x945E455F24FB1CF8}, // 1e69 - {0xB3E2FD538E122B44, 0xB975D6B6EE39E436}, // 1e70 - {0x60DBBCA87196B616, 0xE7D34C64A9C85D44}, // 1e71 - {0xBC8955E946FE31CD, 0x90E40FBEEA1D3A4A}, // 1e72 - {0x6BABAB6398BDBE41, 0xB51D13AEA4A488DD}, // 1e73 - {0xC696963C7EED2DD1, 0xE264589A4DCDAB14}, // 1e74 - {0xFC1E1DE5CF543CA2, 0x8D7EB76070A08AEC}, // 1e75 - {0x3B25A55F43294BCB, 0xB0DE65388CC8ADA8}, // 1e76 - {0x49EF0EB713F39EBE, 0xDD15FE86AFFAD912}, // 1e77 - {0x6E3569326C784337, 0x8A2DBF142DFCC7AB}, // 1e78 - {0x49C2C37F07965404, 0xACB92ED9397BF996}, // 1e79 - {0xDC33745EC97BE906, 0xD7E77A8F87DAF7FB}, // 1e80 - {0x69A028BB3DED71A3, 0x86F0AC99B4E8DAFD}, // 1e81 - {0xC40832EA0D68CE0C, 0xA8ACD7C0222311BC}, // 1e82 - {0xF50A3FA490C30190, 0xD2D80DB02AABD62B}, // 1e83 - {0x792667C6DA79E0FA, 0x83C7088E1AAB65DB}, // 1e84 - {0x577001B891185938, 0xA4B8CAB1A1563F52}, // 1e85 - {0xED4C0226B55E6F86, 0xCDE6FD5E09ABCF26}, // 1e86 - {0x544F8158315B05B4, 0x80B05E5AC60B6178}, // 1e87 - {0x696361AE3DB1C721, 0xA0DC75F1778E39D6}, // 1e88 - {0x03BC3A19CD1E38E9, 0xC913936DD571C84C}, // 1e89 - {0x04AB48A04065C723, 0xFB5878494ACE3A5F}, // 1e90 - {0x62EB0D64283F9C76, 0x9D174B2DCEC0E47B}, // 1e91 - {0x3BA5D0BD324F8394, 0xC45D1DF942711D9A}, // 1e92 - {0xCA8F44EC7EE36479, 0xF5746577930D6500}, // 1e93 - {0x7E998B13CF4E1ECB, 0x9968BF6ABBE85F20}, // 1e94 - {0x9E3FEDD8C321A67E, 0xBFC2EF456AE276E8}, // 1e95 - {0xC5CFE94EF3EA101E, 0xEFB3AB16C59B14A2}, // 1e96 - {0xBBA1F1D158724A12, 0x95D04AEE3B80ECE5}, // 1e97 - {0x2A8A6E45AE8EDC97, 0xBB445DA9CA61281F}, // 1e98 - {0xF52D09D71A3293BD, 0xEA1575143CF97226}, // 1e99 - {0x593C2626705F9C56, 0x924D692CA61BE758}, // 1e100 - {0x6F8B2FB00C77836C, 0xB6E0C377CFA2E12E}, // 1e101 - {0x0B6DFB9C0F956447, 0xE498F455C38B997A}, // 1e102 - {0x4724BD4189BD5EAC, 0x8EDF98B59A373FEC}, // 1e103 - {0x58EDEC91EC2CB657, 0xB2977EE300C50FE7}, // 1e104 - {0x2F2967B66737E3ED, 0xDF3D5E9BC0F653E1}, // 1e105 - {0xBD79E0D20082EE74, 0x8B865B215899F46C}, // 1e106 - {0xECD8590680A3AA11, 0xAE67F1E9AEC07187}, // 1e107 - {0xE80E6F4820CC9495, 0xDA01EE641A708DE9}, // 1e108 - {0x3109058D147FDCDD, 0x884134FE908658B2}, // 1e109 - {0xBD4B46F0599FD415, 0xAA51823E34A7EEDE}, // 1e110 - {0x6C9E18AC7007C91A, 0xD4E5E2CDC1D1EA96}, // 1e111 - {0x03E2CF6BC604DDB0, 0x850FADC09923329E}, // 1e112 - {0x84DB8346B786151C, 0xA6539930BF6BFF45}, // 1e113 - {0xE612641865679A63, 0xCFE87F7CEF46FF16}, // 1e114 - {0x4FCB7E8F3F60C07E, 0x81F14FAE158C5F6E}, // 1e115 - {0xE3BE5E330F38F09D, 0xA26DA3999AEF7749}, // 1e116 - {0x5CADF5BFD3072CC5, 0xCB090C8001AB551C}, // 1e117 - {0x73D9732FC7C8F7F6, 0xFDCB4FA002162A63}, // 1e118 - {0x2867E7FDDCDD9AFA, 0x9E9F11C4014DDA7E}, // 1e119 - {0xB281E1FD541501B8, 0xC646D63501A1511D}, // 1e120 - {0x1F225A7CA91A4226, 0xF7D88BC24209A565}, // 1e121 - {0x3375788DE9B06958, 0x9AE757596946075F}, // 1e122 - {0x0052D6B1641C83AE, 0xC1A12D2FC3978937}, // 1e123 - {0xC0678C5DBD23A49A, 0xF209787BB47D6B84}, // 1e124 - {0xF840B7BA963646E0, 0x9745EB4D50CE6332}, // 1e125 - {0xB650E5A93BC3D898, 0xBD176620A501FBFF}, // 1e126 - {0xA3E51F138AB4CEBE, 0xEC5D3FA8CE427AFF}, // 1e127 - {0xC66F336C36B10137, 0x93BA47C980E98CDF}, // 1e128 - {0xB80B0047445D4184, 0xB8A8D9BBE123F017}, // 1e129 - {0xA60DC059157491E5, 0xE6D3102AD96CEC1D}, // 1e130 - {0x87C89837AD68DB2F, 0x9043EA1AC7E41392}, // 1e131 - {0x29BABE4598C311FB, 0xB454E4A179DD1877}, // 1e132 - {0xF4296DD6FEF3D67A, 0xE16A1DC9D8545E94}, // 1e133 - {0x1899E4A65F58660C, 0x8CE2529E2734BB1D}, // 1e134 - {0x5EC05DCFF72E7F8F, 0xB01AE745B101E9E4}, // 1e135 - {0x76707543F4FA1F73, 0xDC21A1171D42645D}, // 1e136 - {0x6A06494A791C53A8, 0x899504AE72497EBA}, // 1e137 - {0x0487DB9D17636892, 0xABFA45DA0EDBDE69}, // 1e138 - {0x45A9D2845D3C42B6, 0xD6F8D7509292D603}, // 1e139 - {0x0B8A2392BA45A9B2, 0x865B86925B9BC5C2}, // 1e140 - {0x8E6CAC7768D7141E, 0xA7F26836F282B732}, // 1e141 - {0x3207D795430CD926, 0xD1EF0244AF2364FF}, // 1e142 - {0x7F44E6BD49E807B8, 0x8335616AED761F1F}, // 1e143 - {0x5F16206C9C6209A6, 0xA402B9C5A8D3A6E7}, // 1e144 - {0x36DBA887C37A8C0F, 0xCD036837130890A1}, // 1e145 - {0xC2494954DA2C9789, 0x802221226BE55A64}, // 1e146 - {0xF2DB9BAA10B7BD6C, 0xA02AA96B06DEB0FD}, // 1e147 - {0x6F92829494E5ACC7, 0xC83553C5C8965D3D}, // 1e148 - {0xCB772339BA1F17F9, 0xFA42A8B73ABBF48C}, // 1e149 - {0xFF2A760414536EFB, 0x9C69A97284B578D7}, // 1e150 - {0xFEF5138519684ABA, 0xC38413CF25E2D70D}, // 1e151 - {0x7EB258665FC25D69, 0xF46518C2EF5B8CD1}, // 1e152 - {0xEF2F773FFBD97A61, 0x98BF2F79D5993802}, // 1e153 - {0xAAFB550FFACFD8FA, 0xBEEEFB584AFF8603}, // 1e154 - {0x95BA2A53F983CF38, 0xEEAABA2E5DBF6784}, // 1e155 - {0xDD945A747BF26183, 0x952AB45CFA97A0B2}, // 1e156 - {0x94F971119AEEF9E4, 0xBA756174393D88DF}, // 1e157 - {0x7A37CD5601AAB85D, 0xE912B9D1478CEB17}, // 1e158 - {0xAC62E055C10AB33A, 0x91ABB422CCB812EE}, // 1e159 - {0x577B986B314D6009, 0xB616A12B7FE617AA}, // 1e160 - {0xED5A7E85FDA0B80B, 0xE39C49765FDF9D94}, // 1e161 - {0x14588F13BE847307, 0x8E41ADE9FBEBC27D}, // 1e162 - {0x596EB2D8AE258FC8, 0xB1D219647AE6B31C}, // 1e163 - {0x6FCA5F8ED9AEF3BB, 0xDE469FBD99A05FE3}, // 1e164 - {0x25DE7BB9480D5854, 0x8AEC23D680043BEE}, // 1e165 - {0xAF561AA79A10AE6A, 0xADA72CCC20054AE9}, // 1e166 - {0x1B2BA1518094DA04, 0xD910F7FF28069DA4}, // 1e167 - {0x90FB44D2F05D0842, 0x87AA9AFF79042286}, // 1e168 - {0x353A1607AC744A53, 0xA99541BF57452B28}, // 1e169 - {0x42889B8997915CE8, 0xD3FA922F2D1675F2}, // 1e170 - {0x69956135FEBADA11, 0x847C9B5D7C2E09B7}, // 1e171 - {0x43FAB9837E699095, 0xA59BC234DB398C25}, // 1e172 - {0x94F967E45E03F4BB, 0xCF02B2C21207EF2E}, // 1e173 - {0x1D1BE0EEBAC278F5, 0x8161AFB94B44F57D}, // 1e174 - {0x6462D92A69731732, 0xA1BA1BA79E1632DC}, // 1e175 - {0x7D7B8F7503CFDCFE, 0xCA28A291859BBF93}, // 1e176 - {0x5CDA735244C3D43E, 0xFCB2CB35E702AF78}, // 1e177 - {0x3A0888136AFA64A7, 0x9DEFBF01B061ADAB}, // 1e178 - {0x088AAA1845B8FDD0, 0xC56BAEC21C7A1916}, // 1e179 - {0x8AAD549E57273D45, 0xF6C69A72A3989F5B}, // 1e180 - {0x36AC54E2F678864B, 0x9A3C2087A63F6399}, // 1e181 - {0x84576A1BB416A7DD, 0xC0CB28A98FCF3C7F}, // 1e182 - {0x656D44A2A11C51D5, 0xF0FDF2D3F3C30B9F}, // 1e183 - {0x9F644AE5A4B1B325, 0x969EB7C47859E743}, // 1e184 - {0x873D5D9F0DDE1FEE, 0xBC4665B596706114}, // 1e185 - {0xA90CB506D155A7EA, 0xEB57FF22FC0C7959}, // 1e186 - {0x09A7F12442D588F2, 0x9316FF75DD87CBD8}, // 1e187 - {0x0C11ED6D538AEB2F, 0xB7DCBF5354E9BECE}, // 1e188 - {0x8F1668C8A86DA5FA, 0xE5D3EF282A242E81}, // 1e189 - {0xF96E017D694487BC, 0x8FA475791A569D10}, // 1e190 - {0x37C981DCC395A9AC, 0xB38D92D760EC4455}, // 1e191 - {0x85BBE253F47B1417, 0xE070F78D3927556A}, // 1e192 - {0x93956D7478CCEC8E, 0x8C469AB843B89562}, // 1e193 - {0x387AC8D1970027B2, 0xAF58416654A6BABB}, // 1e194 - {0x06997B05FCC0319E, 0xDB2E51BFE9D0696A}, // 1e195 - {0x441FECE3BDF81F03, 0x88FCF317F22241E2}, // 1e196 - {0xD527E81CAD7626C3, 0xAB3C2FDDEEAAD25A}, // 1e197 - {0x8A71E223D8D3B074, 0xD60B3BD56A5586F1}, // 1e198 - {0xF6872D5667844E49, 0x85C7056562757456}, // 1e199 - {0xB428F8AC016561DB, 0xA738C6BEBB12D16C}, // 1e200 - {0xE13336D701BEBA52, 0xD106F86E69D785C7}, // 1e201 - {0xECC0024661173473, 0x82A45B450226B39C}, // 1e202 - {0x27F002D7F95D0190, 0xA34D721642B06084}, // 1e203 - {0x31EC038DF7B441F4, 0xCC20CE9BD35C78A5}, // 1e204 - {0x7E67047175A15271, 0xFF290242C83396CE}, // 1e205 - {0x0F0062C6E984D386, 0x9F79A169BD203E41}, // 1e206 - {0x52C07B78A3E60868, 0xC75809C42C684DD1}, // 1e207 - {0xA7709A56CCDF8A82, 0xF92E0C3537826145}, // 1e208 - {0x88A66076400BB691, 0x9BBCC7A142B17CCB}, // 1e209 - {0x6ACFF893D00EA435, 0xC2ABF989935DDBFE}, // 1e210 - {0x0583F6B8C4124D43, 0xF356F7EBF83552FE}, // 1e211 - {0xC3727A337A8B704A, 0x98165AF37B2153DE}, // 1e212 - {0x744F18C0592E4C5C, 0xBE1BF1B059E9A8D6}, // 1e213 - {0x1162DEF06F79DF73, 0xEDA2EE1C7064130C}, // 1e214 - {0x8ADDCB5645AC2BA8, 0x9485D4D1C63E8BE7}, // 1e215 - {0x6D953E2BD7173692, 0xB9A74A0637CE2EE1}, // 1e216 - {0xC8FA8DB6CCDD0437, 0xE8111C87C5C1BA99}, // 1e217 - {0x1D9C9892400A22A2, 0x910AB1D4DB9914A0}, // 1e218 - {0x2503BEB6D00CAB4B, 0xB54D5E4A127F59C8}, // 1e219 - {0x2E44AE64840FD61D, 0xE2A0B5DC971F303A}, // 1e220 - {0x5CEAECFED289E5D2, 0x8DA471A9DE737E24}, // 1e221 - {0x7425A83E872C5F47, 0xB10D8E1456105DAD}, // 1e222 - {0xD12F124E28F77719, 0xDD50F1996B947518}, // 1e223 - {0x82BD6B70D99AAA6F, 0x8A5296FFE33CC92F}, // 1e224 - {0x636CC64D1001550B, 0xACE73CBFDC0BFB7B}, // 1e225 - {0x3C47F7E05401AA4E, 0xD8210BEFD30EFA5A}, // 1e226 - {0x65ACFAEC34810A71, 0x8714A775E3E95C78}, // 1e227 - {0x7F1839A741A14D0D, 0xA8D9D1535CE3B396}, // 1e228 - {0x1EDE48111209A050, 0xD31045A8341CA07C}, // 1e229 - {0x934AED0AAB460432, 0x83EA2B892091E44D}, // 1e230 - {0xF81DA84D5617853F, 0xA4E4B66B68B65D60}, // 1e231 - {0x36251260AB9D668E, 0xCE1DE40642E3F4B9}, // 1e232 - {0xC1D72B7C6B426019, 0x80D2AE83E9CE78F3}, // 1e233 - {0xB24CF65B8612F81F, 0xA1075A24E4421730}, // 1e234 - {0xDEE033F26797B627, 0xC94930AE1D529CFC}, // 1e235 - {0x169840EF017DA3B1, 0xFB9B7CD9A4A7443C}, // 1e236 - {0x8E1F289560EE864E, 0x9D412E0806E88AA5}, // 1e237 - {0xF1A6F2BAB92A27E2, 0xC491798A08A2AD4E}, // 1e238 - {0xAE10AF696774B1DB, 0xF5B5D7EC8ACB58A2}, // 1e239 - {0xACCA6DA1E0A8EF29, 0x9991A6F3D6BF1765}, // 1e240 - {0x17FD090A58D32AF3, 0xBFF610B0CC6EDD3F}, // 1e241 - {0xDDFC4B4CEF07F5B0, 0xEFF394DCFF8A948E}, // 1e242 - {0x4ABDAF101564F98E, 0x95F83D0A1FB69CD9}, // 1e243 - {0x9D6D1AD41ABE37F1, 0xBB764C4CA7A4440F}, // 1e244 - {0x84C86189216DC5ED, 0xEA53DF5FD18D5513}, // 1e245 - {0x32FD3CF5B4E49BB4, 0x92746B9BE2F8552C}, // 1e246 - {0x3FBC8C33221DC2A1, 0xB7118682DBB66A77}, // 1e247 - {0x0FABAF3FEAA5334A, 0xE4D5E82392A40515}, // 1e248 - {0x29CB4D87F2A7400E, 0x8F05B1163BA6832D}, // 1e249 - {0x743E20E9EF511012, 0xB2C71D5BCA9023F8}, // 1e250 - {0x914DA9246B255416, 0xDF78E4B2BD342CF6}, // 1e251 - {0x1AD089B6C2F7548E, 0x8BAB8EEFB6409C1A}, // 1e252 - {0xA184AC2473B529B1, 0xAE9672ABA3D0C320}, // 1e253 - {0xC9E5D72D90A2741E, 0xDA3C0F568CC4F3E8}, // 1e254 - {0x7E2FA67C7A658892, 0x8865899617FB1871}, // 1e255 - {0xDDBB901B98FEEAB7, 0xAA7EEBFB9DF9DE8D}, // 1e256 - {0x552A74227F3EA565, 0xD51EA6FA85785631}, // 1e257 - {0xD53A88958F87275F, 0x8533285C936B35DE}, // 1e258 - {0x8A892ABAF368F137, 0xA67FF273B8460356}, // 1e259 - {0x2D2B7569B0432D85, 0xD01FEF10A657842C}, // 1e260 - {0x9C3B29620E29FC73, 0x8213F56A67F6B29B}, // 1e261 - {0x8349F3BA91B47B8F, 0xA298F2C501F45F42}, // 1e262 - {0x241C70A936219A73, 0xCB3F2F7642717713}, // 1e263 - {0xED238CD383AA0110, 0xFE0EFB53D30DD4D7}, // 1e264 - {0xF4363804324A40AA, 0x9EC95D1463E8A506}, // 1e265 - {0xB143C6053EDCD0D5, 0xC67BB4597CE2CE48}, // 1e266 - {0xDD94B7868E94050A, 0xF81AA16FDC1B81DA}, // 1e267 - {0xCA7CF2B4191C8326, 0x9B10A4E5E9913128}, // 1e268 - {0xFD1C2F611F63A3F0, 0xC1D4CE1F63F57D72}, // 1e269 - {0xBC633B39673C8CEC, 0xF24A01A73CF2DCCF}, // 1e270 - {0xD5BE0503E085D813, 0x976E41088617CA01}, // 1e271 - {0x4B2D8644D8A74E18, 0xBD49D14AA79DBC82}, // 1e272 - {0xDDF8E7D60ED1219E, 0xEC9C459D51852BA2}, // 1e273 - {0xCABB90E5C942B503, 0x93E1AB8252F33B45}, // 1e274 - {0x3D6A751F3B936243, 0xB8DA1662E7B00A17}, // 1e275 - {0x0CC512670A783AD4, 0xE7109BFBA19C0C9D}, // 1e276 - {0x27FB2B80668B24C5, 0x906A617D450187E2}, // 1e277 - {0xB1F9F660802DEDF6, 0xB484F9DC9641E9DA}, // 1e278 - {0x5E7873F8A0396973, 0xE1A63853BBD26451}, // 1e279 - {0xDB0B487B6423E1E8, 0x8D07E33455637EB2}, // 1e280 - {0x91CE1A9A3D2CDA62, 0xB049DC016ABC5E5F}, // 1e281 - {0x7641A140CC7810FB, 0xDC5C5301C56B75F7}, // 1e282 - {0xA9E904C87FCB0A9D, 0x89B9B3E11B6329BA}, // 1e283 - {0x546345FA9FBDCD44, 0xAC2820D9623BF429}, // 1e284 - {0xA97C177947AD4095, 0xD732290FBACAF133}, // 1e285 - {0x49ED8EABCCCC485D, 0x867F59A9D4BED6C0}, // 1e286 - {0x5C68F256BFFF5A74, 0xA81F301449EE8C70}, // 1e287 - {0x73832EEC6FFF3111, 0xD226FC195C6A2F8C}, // 1e288 - {0xC831FD53C5FF7EAB, 0x83585D8FD9C25DB7}, // 1e289 - {0xBA3E7CA8B77F5E55, 0xA42E74F3D032F525}, // 1e290 - {0x28CE1BD2E55F35EB, 0xCD3A1230C43FB26F}, // 1e291 - {0x7980D163CF5B81B3, 0x80444B5E7AA7CF85}, // 1e292 - {0xD7E105BCC332621F, 0xA0555E361951C366}, // 1e293 - {0x8DD9472BF3FEFAA7, 0xC86AB5C39FA63440}, // 1e294 - {0xB14F98F6F0FEB951, 0xFA856334878FC150}, // 1e295 - {0x6ED1BF9A569F33D3, 0x9C935E00D4B9D8D2}, // 1e296 - {0x0A862F80EC4700C8, 0xC3B8358109E84F07}, // 1e297 - {0xCD27BB612758C0FA, 0xF4A642E14C6262C8}, // 1e298 - {0x8038D51CB897789C, 0x98E7E9CCCFBD7DBD}, // 1e299 - {0xE0470A63E6BD56C3, 0xBF21E44003ACDD2C}, // 1e300 - {0x1858CCFCE06CAC74, 0xEEEA5D5004981478}, // 1e301 - {0x0F37801E0C43EBC8, 0x95527A5202DF0CCB}, // 1e302 - {0xD30560258F54E6BA, 0xBAA718E68396CFFD}, // 1e303 - {0x47C6B82EF32A2069, 0xE950DF20247C83FD}, // 1e304 - {0x4CDC331D57FA5441, 0x91D28B7416CDD27E}, // 1e305 - {0xE0133FE4ADF8E952, 0xB6472E511C81471D}, // 1e306 - {0x58180FDDD97723A6, 0xE3D8F9E563A198E5}, // 1e307 - {0x570F09EAA7EA7648, 0x8E679C2F5E44FF8F}, // 1e308 - {0x2CD2CC6551E513DA, 0xB201833B35D63F73}, // 1e309 - {0xF8077F7EA65E58D1, 0xDE81E40A034BCF4F}, // 1e310 - {0xFB04AFAF27FAF782, 0x8B112E86420F6191}, // 1e311 - {0x79C5DB9AF1F9B563, 0xADD57A27D29339F6}, // 1e312 - {0x18375281AE7822BC, 0xD94AD8B1C7380874}, // 1e313 - {0x8F2293910D0B15B5, 0x87CEC76F1C830548}, // 1e314 - {0xB2EB3875504DDB22, 0xA9C2794AE3A3C69A}, // 1e315 - {0x5FA60692A46151EB, 0xD433179D9C8CB841}, // 1e316 - {0xDBC7C41BA6BCD333, 0x849FEEC281D7F328}, // 1e317 - {0x12B9B522906C0800, 0xA5C7EA73224DEFF3}, // 1e318 - {0xD768226B34870A00, 0xCF39E50FEAE16BEF}, // 1e319 - {0xE6A1158300D46640, 0x81842F29F2CCE375}, // 1e320 - {0x60495AE3C1097FD0, 0xA1E53AF46F801C53}, // 1e321 - {0x385BB19CB14BDFC4, 0xCA5E89B18B602368}, // 1e322 - {0x46729E03DD9ED7B5, 0xFCF62C1DEE382C42}, // 1e323 - {0x6C07A2C26A8346D1, 0x9E19DB92B4E31BA9}, // 1e324 - {0xC7098B7305241885, 0xC5A05277621BE293}, // 1e325 - {0xB8CBEE4FC66D1EA7, 0xF70867153AA2DB38}, // 1e326 - {0x737F74F1DC043328, 0x9A65406D44A5C903}, // 1e327 - {0x505F522E53053FF2, 0xC0FE908895CF3B44}, // 1e328 - {0x647726B9E7C68FEF, 0xF13E34AABB430A15}, // 1e329 - {0x5ECA783430DC19F5, 0x96C6E0EAB509E64D}, // 1e330 - {0xB67D16413D132072, 0xBC789925624C5FE0}, // 1e331 - {0xE41C5BD18C57E88F, 0xEB96BF6EBADF77D8}, // 1e332 - {0x8E91B962F7B6F159, 0x933E37A534CBAAE7}, // 1e333 - {0x723627BBB5A4ADB0, 0xB80DC58E81FE95A1}, // 1e334 - {0xCEC3B1AAA30DD91C, 0xE61136F2227E3B09}, // 1e335 - {0x213A4F0AA5E8A7B1, 0x8FCAC257558EE4E6}, // 1e336 - {0xA988E2CD4F62D19D, 0xB3BD72ED2AF29E1F}, // 1e337 - {0x93EB1B80A33B8605, 0xE0ACCFA875AF45A7}, // 1e338 - {0xBC72F130660533C3, 0x8C6C01C9498D8B88}, // 1e339 - {0xEB8FAD7C7F8680B4, 0xAF87023B9BF0EE6A}, // 1e340 - {0xA67398DB9F6820E1, 0xDB68C2CA82ED2A05}, // 1e341 - {0x88083F8943A1148C, 0x892179BE91D43A43}, // 1e342 - {0x6A0A4F6B948959B0, 0xAB69D82E364948D4}, // 1e343 - {0x848CE34679ABB01C, 0xD6444E39C3DB9B09}, // 1e344 - {0xF2D80E0C0C0B4E11, 0x85EAB0E41A6940E5}, // 1e345 - {0x6F8E118F0F0E2195, 0xA7655D1D2103911F}, // 1e346 - {0x4B7195F2D2D1A9FB, 0xD13EB46469447567}, // 1e347 -} diff --git a/util/gnolanddev/strconv/ftoaryu_test.gno b/util/gnolanddev/strconv/ftoaryu_test.gno deleted file mode 100644 index bd969e8e..00000000 --- a/util/gnolanddev/strconv/ftoaryu_test.gno +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package strconv - -import ( - "math" - "testing" -) - -func TestMulByLog2Log10(t *testing.T) { - for x := -1600; x <= +1600; x++ { - iMath := MulByLog2Log10(x) - fMath := int(math.Floor(float64(x) * math.Ln2 / math.Ln10)) - if iMath != fMath { - t.Errorf("mulByLog2Log10(%d) failed: %d vs %d\n", x, iMath, fMath) - } - } -} - -func TestMulByLog10Log2(t *testing.T) { - for x := -500; x <= +500; x++ { - iMath := MulByLog10Log2(x) - fMath := int(math.Floor(float64(x) * math.Ln10 / math.Ln2)) - if iMath != fMath { - t.Errorf("mulByLog10Log2(%d) failed: %d vs %d\n", x, iMath, fMath) - } - } -} diff --git a/util/gnolanddev/strconv/internal_test.gno b/util/gnolanddev/strconv/internal_test.gno deleted file mode 100644 index f51d4934..00000000 --- a/util/gnolanddev/strconv/internal_test.gno +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// export access to strconv internals for tests - -package strconv - -func NewDecimal(i uint64) *decimal { - d := new(decimal) - d.Assign(i) - return d -} - -func MulByLog2Log10(x int) int { - return mulByLog2Log10(x) -} - -func MulByLog10Log2(x int) int { - return mulByLog10Log2(x) -} From 3ce64e3f62ae9e419cd975b254fdb6c3a617a617 Mon Sep 17 00:00:00 2001 From: Morgan Bazalgette Date: Fri, 9 Feb 2024 14:51:20 +0100 Subject: [PATCH 05/13] re-organise makefile --- Makefile | 138 +++++++++++++++++-------------------------------- faucet/go.mod | 8 +-- faucet/go.sum | 18 ++++--- faucet/main.go | 2 +- 4 files changed, 63 insertions(+), 103 deletions(-) diff --git a/Makefile b/Makefile index f8782376..4b1ad9f8 100644 --- a/Makefile +++ b/Makefile @@ -3,26 +3,26 @@ default: help GNOKEY ?= go run github.com/gnolang/gno/gno.land/cmd/gnokey GNOLAND ?= go run github.com/gnolang/gno/gno.land/cmd/gnoland +GNOCMD ?= go run github.com/gnolang/gno/gnovm/cmd/gno GNODEV ?= go run github.com/gnolang/gno/contribs/gnodev GNOROOT ?= `gno env GNOROOT` GNO_TEST_FLAGS ?= -verbose -run '^Test(?:[^P]|P[^e]|Pe[^r])' GNO_TEST_PKGS ?= gno.land/p/demo/chess/... gno.land/r/demo/chess +MNEMONIC_TEST1 ?= source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast + .PHONY: help help: ## Display this help message. - @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[0-9a-zA-Z_-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 }' $(MAKEFILE_LIST) - -.PHONY: dev -dev: - $(GNODEV) ./package/glicko2 ./package/zobrist ./package ./realm + @awk 'BEGIN {FS = ":.*##"; printf "Usage: make [\033[36m\033[0m...]\n"} /^[0-9a-zA-Z_\.-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 }' $(MAKEFILE_LIST) .PHONY: clean -clean: +clean: ## Remove temporary files. find . -name '*.gen.go' -exec rm -rf {} + + rm -rf .test .PHONY: test -test: +test: ## Test packages and realms. rm -rf .test # Create fake GNOROOT with stdlibs, testing stdlibs, and p/ dependencies. # This is currently necessary as gno.mod's `replace` functionality is not linked with the VM. @@ -36,100 +36,58 @@ test: cp -r "$(PWD)/package" ".test/examples/gno.land/p/demo/chess" cp -r "$(PWD)/realm" ".test/examples/gno.land/r/demo/chess" # Test. - cd .test/examples; GNOROOT="$(PWD)/.test" gno test $(GNO_TEST_FLAGS) $(GNO_TEST_PKGS) - -0_setup_gnokey: ## Add an account that will be used for Realm deployment (to gnokey). - printf '\n\n%s\n\n' "source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast" | $(GNOKEY) add --recover --insecure-password-stdin DeployKey || true - $(GNOKEY) list | grep DeployKey + cd .test/examples; GNOROOT="$(PWD)/.test" $(GNOCMD) test $(GNO_TEST_FLAGS) $(GNO_TEST_PKGS) -1_run_gnoland: ## Run the gnoland node. - go mod download -x - rm -rf .tmp/gnoland - mkdir -p .tmp/gnoland - cp -rf `go list -m -mod=mod -f '{{.Dir}}' github.com/gnolang/gno`/gno.land .tmp/gnoland/gno.land - cp -rf `go list -m -mod=mod -f '{{.Dir}}' github.com/gnolang/gno`/examples .tmp/gnoland/examples - chmod -R u+w .tmp/gnoland - ( \ - echo g1plqds6kxnfaqcpky0gtt6fpntfhjgcfx8r73a0=100000000000000000ugnot; \ - echo g1sgy2zhqg2wecuz3qt8th63d539afagjnhs4zj3=100000000000000000ugnot; \ - echo g1unk9a8yt595p4yxpfpejewvf9lx6yrvd2ylgtm=100000000000000000ugnot; \ - echo g17x4qwuhmc6fyp6ut2qtscc9265xe5jnj83s8c6=100000000000000000ugnot; \ - echo g1agq8t3289xxmm63z55axykmmve2pz87yqgyn5n=100000000000000000ugnot; \ - echo g153xesqpfvr5y35l0aykew3796kz452zttp0xt2=100000000000000000ugnot; \ - echo g18epncd7avkhmdlf930e4t2p7c7j9qdv3yda93f=100000000000000000ugnot; \ - echo g1elguymy8sjjy246u09qddtx587934k6uzf8mc4=100000000000000000ugnot; \ - echo g1sl70rzvu49mp0lstxaptmvle8h2a8rx8pu56uk=100000000000000000ugnot; \ - echo g18dgugclk93v65qtxxus82eg30af59fgk246nqy=100000000000000000ugnot; \ - ) >> .tmp/gnoland/gno.land/genesis/genesis_balances.txt - ln -s `go list -m -mod=mod -f '{{.Dir}}' github.com/gnolang/gno`/gnovm .tmp/gnoland/gnovm - #mkdir -p .tmp/gnoland/gno.land/testdir/config - #cp ./util/devnet/config.toml .tmp/gnoland/gno.land/testdir/config/config.toml - cd .tmp/gnoland/gno.land; $(GNOLAND) start \ - -genesis-max-vm-cycles 100000000 +gnokey.add_test1: ## Add an account that will be used for Realm deployment (to gnokey). + printf '\n\n%s\n\n' "$(MNEMONIC_TEST1)" | $(GNOKEY) add --recover --insecure-password-stdin test1 || true + $(GNOKEY) list | grep test1 -2_run_faucet: ## Run the GnoChess faucet. +run.faucet: ## Run the GnoChess faucet. cd faucet; go run main.go \ -fund-limit 250000000ugnot \ - -send-amount 1000000000ugnot \ - -tokens juhb8a7p1D -tokens 6wrBVqzBgQ -tokens Ko3z72NaQm -tokens 6j7v0lDR39 -tokens xqh4stG702 \ - -tokens lWGjlfP5rs -tokens UG8f8igNO6 -tokens b3JUurpCFb -tokens 4azfjy6hE9 -tokens dzNR5KAz2r \ - -tokens lZOO7O5OeE -tokens epxa67WQ2c -tokens GnfMj2sDCO -tokens kDN7hiiSWE -tokens OtLfdJC279 \ - -tokens GNZi9TlXBu -tokens 6sVZv0ww7v -tokens SdmrRLKXcx -tokens 8GfDC6ODwr -tokens 783xSVRGbI \ - -tokens Ahphohei4b -tokens uPulohsh4f -tokens aigeVah1El -tokens wuchi4feeP -tokens Ae9weim0OK \ - -tokens ieb2Leik7e -tokens pohJ9oozoo -tokens xoKaesh3ae -tokens di6eeYooco -tokens bahti5ek0L \ - -tokens Uu5quoh6Oo -tokens Phaix9Ahcu -tokens maiGh8ziew -tokens ohPhoo9aev -tokens aeveV5ohgh \ - -tokens ceJ1reexoa -tokens rash0Ku5ha -tokens shaequoh7P -tokens NiLiesah3u -tokens Pion1Phie9 \ - -tokens ahkiev9Foo -tokens uaXiJ7eine -tokens thoTej9yo9 -tokens eiTee2Eizu -tokens ier6oaQu5p \ - -tokens fahoSoa5ee -tokens boet9fo2Ek -tokens ugh9Iedai7 -tokens no7ohsaiXo -tokens ahViquie5Z \ - -tokens Iquae8oozo -tokens Esh5on7eiT -tokens Moop1eekoo -tokens gae6uo5Sae -tokens fei9aufeeX \ - -tokens chee6aC9ph -tokens zongo0Coe3 -tokens Leing1pi0a -tokens ekai5Aih8N -tokens Kasu3es5ch \ - -tokens eeChe1OhKu -tokens Al9Oojoo3I -tokens Xohwate0AT -tokens eef1ieJu1m -tokens eeGh4rohfi \ - -tokens cah3Shohye -tokens eiZ7eish3t -tokens aiF9LieTie -tokens she6eeceeP -tokens teev5Moh6t \ - -tokens Zae2ailitu -tokens seech3Eice -tokens iju8Aegeeh -tokens quooth6iZa -tokens Fae3ohng1o \ - -tokens Caibal9ahx -tokens iaPhoow2ha -tokens Iethee8Wu0 -tokens ahsahgh3Do -tokens Aithai7ahz \ - -tokens wocie7pe8O -tokens PhaelahN0B -tokens boon4Yohth -tokens ohke9Pha0o -tokens UYieShez6a \ - -tokens aR8zaeWee0 -tokens ka0aeVai6z -tokens Oi6oThaez1 -tokens oodee5INga -tokens Aet6WeePu8 \ - -tokens Fieroo3Xai -tokens Is4neath2N -tokens EeliegeiT8 -tokens Ahg9aishi8 -tokens aj4mah9Daa \ - -tokens Sheish0foo -tokens ooseethoM8 -tokens Xaiphai8no -tokens ni9eeLei9f -tokens ieveiwai3E \ - -tokens mooQuag4ee -tokens ZaeRieph2j -tokens AeY8iPioh4 -tokens Huar8iemee -tokens shoo5Loh8z \ - -tokens ohz8Reetev -tokens Eotahh4aja -tokens Xae9ciew9B -tokens aeVe1Oethe -tokens eihah2Ahw7 \ - -tokens Chai8laile -tokens ku9iax9Cho -tokens Ahl4veihud -tokens FaShutaj2v -tokens nahS6iu0Yi \ - -tokens Ohzaj5wi2m -tokens EeL0Agee0e -tokens eePhie7tho -tokens Eisai2ew6E -tokens woiyoo6Xee \ - -mnemonic "piano aim fashion palace key scrap write garage avocado royal lounge lumber remove frozen sketch maze tree model half team cook burden pattern choice" \ - -num-accounts 10 - -3_run_web: ## Run the web server. + -send-amount 1000000000ugnot \ + -chain-id tendermint_test \ + -tokens juhb8a7p1D -tokens 6wrBVqzBgQ -tokens Ko3z72NaQm -tokens 6j7v0lDR39 -tokens xqh4stG702 \ + -tokens lWGjlfP5rs -tokens UG8f8igNO6 -tokens b3JUurpCFb -tokens 4azfjy6hE9 -tokens dzNR5KAz2r \ + -tokens lZOO7O5OeE -tokens epxa67WQ2c -tokens GnfMj2sDCO -tokens kDN7hiiSWE -tokens OtLfdJC279 \ + -tokens GNZi9TlXBu -tokens 6sVZv0ww7v -tokens SdmrRLKXcx -tokens 8GfDC6ODwr -tokens 783xSVRGbI \ + -tokens Ahphohei4b -tokens uPulohsh4f -tokens aigeVah1El -tokens wuchi4feeP -tokens Ae9weim0OK \ + -tokens ieb2Leik7e -tokens pohJ9oozoo -tokens xoKaesh3ae -tokens di6eeYooco -tokens bahti5ek0L \ + -tokens Uu5quoh6Oo -tokens Phaix9Ahcu -tokens maiGh8ziew -tokens ohPhoo9aev -tokens aeveV5ohgh \ + -tokens ceJ1reexoa -tokens rash0Ku5ha -tokens shaequoh7P -tokens NiLiesah3u -tokens Pion1Phie9 \ + -tokens ahkiev9Foo -tokens uaXiJ7eine -tokens thoTej9yo9 -tokens eiTee2Eizu -tokens ier6oaQu5p \ + -tokens fahoSoa5ee -tokens boet9fo2Ek -tokens ugh9Iedai7 -tokens no7ohsaiXo -tokens ahViquie5Z \ + -tokens Iquae8oozo -tokens Esh5on7eiT -tokens Moop1eekoo -tokens gae6uo5Sae -tokens fei9aufeeX \ + -tokens chee6aC9ph -tokens zongo0Coe3 -tokens Leing1pi0a -tokens ekai5Aih8N -tokens Kasu3es5ch \ + -tokens eeChe1OhKu -tokens Al9Oojoo3I -tokens Xohwate0AT -tokens eef1ieJu1m -tokens eeGh4rohfi \ + -tokens cah3Shohye -tokens eiZ7eish3t -tokens aiF9LieTie -tokens she6eeceeP -tokens teev5Moh6t \ + -tokens Zae2ailitu -tokens seech3Eice -tokens iju8Aegeeh -tokens quooth6iZa -tokens Fae3ohng1o \ + -tokens Caibal9ahx -tokens iaPhoow2ha -tokens Iethee8Wu0 -tokens ahsahgh3Do -tokens Aithai7ahz \ + -tokens wocie7pe8O -tokens PhaelahN0B -tokens boon4Yohth -tokens ohke9Pha0o -tokens UYieShez6a \ + -tokens aR8zaeWee0 -tokens ka0aeVai6z -tokens Oi6oThaez1 -tokens oodee5INga -tokens Aet6WeePu8 \ + -tokens Fieroo3Xai -tokens Is4neath2N -tokens EeliegeiT8 -tokens Ahg9aishi8 -tokens aj4mah9Daa \ + -tokens Sheish0foo -tokens ooseethoM8 -tokens Xaiphai8no -tokens ni9eeLei9f -tokens ieveiwai3E \ + -tokens mooQuag4ee -tokens ZaeRieph2j -tokens AeY8iPioh4 -tokens Huar8iemee -tokens shoo5Loh8z \ + -tokens ohz8Reetev -tokens Eotahh4aja -tokens Xae9ciew9B -tokens aeVe1Oethe -tokens eihah2Ahw7 \ + -tokens Chai8laile -tokens ku9iax9Cho -tokens Ahl4veihud -tokens FaShutaj2v -tokens nahS6iu0Yi \ + -tokens Ohzaj5wi2m -tokens EeL0Agee0e -tokens eePhie7tho -tokens Eisai2ew6E -tokens woiyoo6Xee \ + -mnemonic "$(MNEMONIC_TEST1)" \ + -num-accounts 1 + +run.web: ## Run the web server. cd web; npm install ( \ - echo "VITE_GNO_WS_URL=ws://127.0.0.1:26657/websocket"; \ + echo "VITE_GNO_WS_URL=ws://127.0.0.1:36657/websocket"; \ echo "VITE_GNO_CHESS_REALM=gno.land/r/demo/chess"; \ echo "VITE_FAUCET_URL=http://127.0.0.1:8545"; \ - echo "VITE_GNO_JSONRPC_URL=http://127.0.0.1:26657"; \ + echo "VITE_GNO_JSONRPC_URL=http://127.0.0.1:36657"; \ ) > web/.env cp web/.env web/assets/js/.env cd web; npm run build cd web; npm run dev -4_deploy_realm: ## Deploy GnoChess realm on local node. - echo | $(GNOKEY) maketx addpkg \ - --insecure-password-stdin \ - --gas-wanted 20000000 \ - --gas-fee 1ugnot \ - --pkgpath gno.land/r/demo/chess \ - --pkgdir ./realm \ - --broadcast \ - DeployKey - -z_use_local_gno: ## Use the local '../gno' directory instead of the remote 'github.com/gnolang/gno' module. - @echo "Switching to local gno module..." - @go mod edit -replace github.com/gnolang/gno=../gno - -z_use_remote_gno: ## Use the remote 'github.com/gnolang/gno' module and remove any replacements. - @echo "Switching to remote gno module..." - @go mod edit -dropreplace github.com/gnolang/gno - -z_test_realm: ## Test the realm. - go run github.com/gnolang/gno/gnovm/cmd/gno test --verbose ./realm +run.gnodev: ## Run gnodev with the gnochess packages and realm. + $(GNODEV) ./package/glicko2 ./package/zobrist ./package ./realm z_test_integration: ## Test the realm. go test -v -run='TestIntegration/.*' . @@ -137,8 +95,8 @@ z_test_integration: ## Test the realm. z_build_realm: ## Precompile and build the generated Go files. Assumes a working clone of gno in ../gno. mkdir -p ../gno/examples/gno.land/r/gnochess cp -rf realm/*.gno ../gno/examples/gno.land/r/gnochess - go run github.com/gnolang/gno/gnovm/cmd/gno precompile --verbose ../gno/examples/gno.land - go run github.com/gnolang/gno/gnovm/cmd/gno build --verbose ../gno/examples/gno.land/r/gnochess + $(GNOCMD) precompile --verbose ../gno/examples/gno.land + $(GNOCMD) build --verbose ../gno/examples/gno.land/r/gnochess z_poormans_dashboard: @( \ diff --git a/faucet/go.mod b/faucet/go.mod index eee30d51..9e74358c 100644 --- a/faucet/go.mod +++ b/faucet/go.mod @@ -3,12 +3,12 @@ module github.com/gnolang/gnochess-faucet go 1.20 require ( - github.com/gnolang/faucet v0.0.0-20230916181707-934303e1b40d + github.com/gnolang/faucet v0.0.0-20240112121623-353b2f2ae616 github.com/gnolang/gno v0.0.0-20230914214026-ef6a55bf9db2 github.com/peterbourgon/ff/v3 v3.4.0 github.com/redis/go-redis/v9 v9.2.0 go.uber.org/zap v1.26.0 - golang.org/x/sync v0.3.0 + golang.org/x/sync v0.6.0 ) require ( @@ -22,7 +22,7 @@ require ( github.com/dustin/go-humanize v1.0.0 // indirect github.com/gnolang/goleveldb v0.0.9 // indirect github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216 // indirect - github.com/go-chi/chi/v5 v5.0.10 // indirect + github.com/go-chi/chi/v5 v5.0.11 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 // indirect @@ -36,7 +36,7 @@ require ( github.com/linxGnu/grocksdb v1.8.4 // indirect github.com/pelletier/go-toml v1.9.5 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/rs/cors v1.10.0 // indirect + github.com/rs/cors v1.10.1 // indirect github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect go.etcd.io/bbolt v1.3.7 // indirect go.opencensus.io v0.22.5 // indirect diff --git a/faucet/go.sum b/faucet/go.sum index 641a4e78..f05d7dfa 100644 --- a/faucet/go.sum +++ b/faucet/go.sum @@ -25,6 +25,7 @@ github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -49,16 +50,16 @@ github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpm github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/gnolang/faucet v0.0.0-20230916181707-934303e1b40d h1:BNpijDc+VMZrw9DYbtwC94TBKEyMW/Dn3fv/h0gsfPA= -github.com/gnolang/faucet v0.0.0-20230916181707-934303e1b40d/go.mod h1:LEZJ9cCyK7PCb63RB543pTU/lbchePJPmz74MymilO0= +github.com/gnolang/faucet v0.0.0-20240112121623-353b2f2ae616 h1:ktxBGpRZjl70Mw/874im7EJghXJxuA0JUFlBkUHEPkA= +github.com/gnolang/faucet v0.0.0-20240112121623-353b2f2ae616/go.mod h1:FHQwuzmzgUoYKbnmRS8c6dV1exF6ccz5318fMSM4yvM= github.com/gnolang/gno v0.0.0-20230914214026-ef6a55bf9db2 h1:/j3GhCiNnE04Yc+zF+ouY7sZuopGwYx6R9NPipSVVLE= github.com/gnolang/gno v0.0.0-20230914214026-ef6a55bf9db2/go.mod h1:dtwSoPiPCcGxACg4y2iJVWZ/vuU133n4kwF28mx6Krg= github.com/gnolang/goleveldb v0.0.9 h1:Q7rGko9oXMKtQA+Apeeed5a3sjba/mcDhzJGoTVLCKE= github.com/gnolang/goleveldb v0.0.9/go.mod h1:Dz6p9bmpy/FBESTgduiThZt5mToVDipcHGzj/zUOo8E= github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216 h1:GKvsK3oLWG9B1GL7WP/VqwM6C92j5tIvB844oggL9Lk= github.com/gnolang/overflow v0.0.0-20170615021017-4d914c927216/go.mod h1:xJhtEL7ahjM1WJipt89gel8tHzfIl/LyMY+lCYh38d8= -github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk= -github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-chi/chi/v5 v5.0.11 h1:BnpYbFZ3T3S1WMpD79r7R5ThWX40TaFB7L31Y8xqSwA= +github.com/go-chi/chi/v5 v5.0.11/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= @@ -123,8 +124,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/redis/go-redis/v9 v9.2.0 h1:zwMdX0A4eVzse46YN18QhuDiM4uf3JmkOB4VZrdt5uI= github.com/redis/go-redis/v9 v9.2.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= -github.com/rs/cors v1.10.0 h1:62NOS1h+r8p1mW6FM0FSB0exioXLhd/sh15KpjWBZ+8= -github.com/rs/cors v1.10.0/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= +github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo= +github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= @@ -187,8 +188,8 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= +golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -209,6 +210,7 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/faucet/main.go b/faucet/main.go index 7df63d51..36333009 100644 --- a/faucet/main.go +++ b/faucet/main.go @@ -37,7 +37,7 @@ const ( defaultGasFee = "1000000ugnot" defaultGasWanted = "100000" defaultFundLimit = "100ugnot" - defaultRemote = "http://127.0.0.1:26657" + defaultRemote = "http://127.0.0.1:36657" ) const ( From 5a394eaf3270cd620439933a50e25aa0f5439daf Mon Sep 17 00:00:00 2001 From: Morgan Bazalgette Date: Fri, 9 Feb 2024 15:11:54 +0100 Subject: [PATCH 06/13] attempt ci fix --- .github/workflows/{rules.yml => perft.yml} | 8 +- .github/workflows/realm.yml | 3 +- Makefile | 26 +- realm/lobby.gno | 2 +- util/gnolanddev/Dockerfile | 25 - util/gnolanddev/config.toml | 237 -- .../pull-1048-assertorigincall.diff | 1964 ----------------- util/gnolanddev/run.sh | 26 - 8 files changed, 24 insertions(+), 2267 deletions(-) rename .github/workflows/{rules.yml => perft.yml} (69%) delete mode 100644 util/gnolanddev/Dockerfile delete mode 100644 util/gnolanddev/config.toml delete mode 100644 util/gnolanddev/pull-1048-assertorigincall.diff delete mode 100755 util/gnolanddev/run.sh diff --git a/.github/workflows/rules.yml b/.github/workflows/perft.yml similarity index 69% rename from .github/workflows/rules.yml rename to .github/workflows/perft.yml index ab4b62a1..f1def1e5 100644 --- a/.github/workflows/rules.yml +++ b/.github/workflows/perft.yml @@ -1,9 +1,11 @@ -name: rules +name: perft on: pull_request: paths: - - "realm/rules.gno" + - "package/**" + - "Makefile" + - "go.sum" push: branches: - master @@ -19,4 +21,4 @@ jobs: with: go-version: 'stable' - run: go mod download -x - - run: go run github.com/gnolang/gno/gnovm/cmd/gno test -verbose -run 'TestPerft' ./realm + - run: make test.perft diff --git a/.github/workflows/realm.yml b/.github/workflows/realm.yml index bf3d3fe7..f89c98b0 100644 --- a/.github/workflows/realm.yml +++ b/.github/workflows/realm.yml @@ -4,6 +4,7 @@ on: pull_request: paths: - "realm/**" + - "packages/**" - "Makefile" - "go.sum" push: @@ -21,4 +22,4 @@ jobs: with: go-version: 'stable' - run: go mod download -x - - run: go run github.com/gnolang/gno/gnovm/cmd/gno test -verbose ./realm + - run: make test diff --git a/Makefile b/Makefile index 4b1ad9f8..fdfadb2e 100644 --- a/Makefile +++ b/Makefile @@ -7,22 +7,22 @@ GNOCMD ?= go run github.com/gnolang/gno/gnovm/cmd/gno GNODEV ?= go run github.com/gnolang/gno/contribs/gnodev GNOROOT ?= `gno env GNOROOT` -GNO_TEST_FLAGS ?= -verbose -run '^Test(?:[^P]|P[^e]|Pe[^r])' +GNO_TEST_FLAGS ?= -verbose GNO_TEST_PKGS ?= gno.land/p/demo/chess/... gno.land/r/demo/chess MNEMONIC_TEST1 ?= source bonus chronic canvas draft south burst lottery vacant surface solve popular case indicate oppose farm nothing bullet exhibit title speed wink action roast .PHONY: help help: ## Display this help message. - @awk 'BEGIN {FS = ":.*##"; printf "Usage: make [\033[36m\033[0m...]\n"} /^[0-9a-zA-Z_\.-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 }' $(MAKEFILE_LIST) + @awk 'BEGIN {FS = ":.*##"; printf "Usage: make [\033[36m\033[0m...]\n"} /^[[0-9a-zA-Z_\.-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 }' $(MAKEFILE_LIST) .PHONY: clean clean: ## Remove temporary files. find . -name '*.gen.go' -exec rm -rf {} + rm -rf .test -.PHONY: test -test: ## Test packages and realms. +.PHONY: test.prepare +test.prepare: rm -rf .test # Create fake GNOROOT with stdlibs, testing stdlibs, and p/ dependencies. # This is currently necessary as gno.mod's `replace` functionality is not linked with the VM. @@ -35,12 +35,14 @@ test: ## Test packages and realms. # Copy over gnochess code. cp -r "$(PWD)/package" ".test/examples/gno.land/p/demo/chess" cp -r "$(PWD)/realm" ".test/examples/gno.land/r/demo/chess" - # Test. - cd .test/examples; GNOROOT="$(PWD)/.test" $(GNOCMD) test $(GNO_TEST_FLAGS) $(GNO_TEST_PKGS) -gnokey.add_test1: ## Add an account that will be used for Realm deployment (to gnokey). - printf '\n\n%s\n\n' "$(MNEMONIC_TEST1)" | $(GNOKEY) add --recover --insecure-password-stdin test1 || true - $(GNOKEY) list | grep test1 +.PHONY: test +test: test.prepare ## Test packages and realms. + cd .test/examples; GNOROOT="$(PWD)/.test" $(GNOCMD) test -run '^Test(?:[^P]|P[^e]|Pe[^r])' $(GNO_TEST_FLAGS) $(GNO_TEST_PKGS) + +.PHONY: test.perft +test.perft: test.prepare ## Run perft tests. + cd .test/examples; GNOROOT="$(PWD)/.test" $(GNOCMD) test -run 'TestPerft' $(GNO_TEST_FLAGS) gno.land/p/demo/chess run.faucet: ## Run the GnoChess faucet. cd faucet; go run main.go \ @@ -89,7 +91,11 @@ run.web: ## Run the web server. run.gnodev: ## Run gnodev with the gnochess packages and realm. $(GNODEV) ./package/glicko2 ./package/zobrist ./package ./realm -z_test_integration: ## Test the realm. +z_add_test1: ## Add the test1 key to gnokey. + printf '\n\n%s\n\n' "$(MNEMONIC_TEST1)" | $(GNOKEY) add --recover --insecure-password-stdin test1 || true + $(GNOKEY) list | grep test1 + +z_test_integration: ## Test the realm using integration tests. go test -v -run='TestIntegration/.*' . z_build_realm: ## Precompile and build the generated Go files. Assumes a working clone of gno in ../gno. diff --git a/realm/lobby.gno b/realm/lobby.gno index e9b6ff3e..9603a43c 100644 --- a/realm/lobby.gno +++ b/realm/lobby.gno @@ -65,7 +65,7 @@ var ( ) func LobbyJoin(seconds, increment int) { - std.AssertOriginCall() + assertOriginCall() var tc tcLobby switch { diff --git a/util/gnolanddev/Dockerfile b/util/gnolanddev/Dockerfile deleted file mode 100644 index c609d6ac..00000000 --- a/util/gnolanddev/Dockerfile +++ /dev/null @@ -1,25 +0,0 @@ -FROM ghcr.io/gnolang/gno:latest - -# entr: hot reloading -# dumb-init: signal handling, pid 1 -# rsync: used by run.sh to intelligently copy files -# git, golang: used for applying patches and re-build gno binaries following that -RUN apt-get update && \ - apt-get install -y entr dumb-init rsync git golang - -# symlinked by run.sh -ENV GNOROOT="/opt/gnoroot" - -# XXX: apply patch from PR #1048. -WORKDIR /opt/gno/src -ADD ./pull-1048-assertorigincall.diff . -RUN git apply ./pull-1048-assertorigincall.diff && \ - go build -o /opt/gno/bin/gnoland ./gno.land/cmd/gnoland && \ - go build -o /opt/gno/bin/gno ./gnovm/cmd/gno - -# XXX: add strconv float functions (needed for FormatFloat) -ADD ./strconv ./gnovm/stdlibs/strconv - -WORKDIR /opt/gnoroot -CMD [ "dumb-init", "sh", "-c", "while true; do find /mnt -name '*.gno' | entr -drn /run.sh; done" ] -ADD ./run.sh /run.sh diff --git a/util/gnolanddev/config.toml b/util/gnolanddev/config.toml deleted file mode 100644 index f189fad9..00000000 --- a/util/gnolanddev/config.toml +++ /dev/null @@ -1,237 +0,0 @@ -# This is a TOML config file. -# For more information, see https://github.com/toml-lang/toml - -##### main base config options ##### - -# TCP or UNIX socket address of the ABCI application, -# or the name of an ABCI application compiled in with the Tendermint binary -proxy_app = "tcp://0.0.0.0:26658" - -# A custom human readable name for this node -moniker = "45-79-178-97" - -# If this node is many blocks behind the tip of the chain, FastSync -# allows them to catchup quickly by downloading blocks in parallel -# and verifying their commits -fast_sync = true - -# Database backend: goleveldb | cleveldb | boltdb -# * goleveldb (github.com/gnolang/goleveldb, fork of github.com/syndtr/goleveldb) - most popular implementation) -# - pure go -# - stable -# * cleveldb (uses levigo wrapper) -# - fast -# - requires gcc -# - use cleveldb build tag (go build -tags cleveldb) -# * boltdb (uses etcd's fork of bolt - go.etcd.io/bbolt) -# - EXPERIMENTAL -# - may be faster is some use-cases (random reads - indexer) -# - use boltdb build tag (go build -tags boltdb) -db_backend = "goleveldb" - -# Database directory -db_dir = "data" - -# Output level for logging, including package level options -log_level = "main:info,state:info,*:error" - -# Output format: 'plain' (colored text) or 'json' -log_format = "plain" - -##### additional base config options ##### - -# Path to the JSON file containing the initial validator set and other meta data -genesis_file = "config/genesis.json" - -# Path to the JSON file containing the private key to use as a validator in the consensus protocol -priv_validator_key_file = "config/priv_validator_key.json" - -# Path to the JSON file containing the last sign state of a validator -priv_validator_state_file = "data/priv_validator_state.json" - -# TCP or UNIX socket address for Tendermint to listen on for -# connections from an external PrivValidator process -priv_validator_laddr = "" - -# Path to the JSON file containing the private key to use for node authentication in the p2p protocol -node_key_file = "config/node_key.json" - -# Mechanism to connect to the ABCI application: socket | grpc -abci = "socket" - -# TCP or UNIX socket address for the profiling server to listen on -prof_laddr = "" - -# If true, query the ABCI app on connecting to a new peer -# so the app can decide if we should keep the connection or not -filter_peers = false - -##### advanced configuration options ##### - -##### rpc server configuration options ##### -[rpc] - -# TCP or UNIX socket address for the RPC server to listen on -laddr = "tcp://0.0.0.0:26657" - -# A list of origins a cross-domain request can be executed from -# Default value '[]' disables cors support -# Use '["*"]' to allow any origin -cors_allowed_origins = ["*"] - -# A list of methods the client is allowed to use with cross-domain requests -cors_allowed_methods = ["HEAD", "GET", "POST", ] - -# A list of non simple headers the client is allowed to use with cross-domain requests -cors_allowed_headers = ["Origin", "Accept", "Content-Type", "X-Requested-With", "X-Server-Time", ] - -# TCP or UNIX socket address for the gRPC server to listen on -# NOTE: This server only supports /broadcast_tx_commit -grpc_laddr = "" - -# Maximum number of simultaneous connections. -# Does not include RPC (HTTP&WebSocket) connections. See max_open_connections -# If you want to accept a larger number than the default, make sure -# you increase your OS limits. -# 0 - unlimited. -# Should be < {ulimit -Sn} - {MaxNumInboundPeers} - {MaxNumOutboundPeers} - {N of wal, db and other open files} -# 1024 - 40 - 10 - 50 = 924 = ~900 -grpc_max_open_connections = 900 - -# Activate unsafe RPC commands like /dial_seeds and /unsafe_flush_mempool -unsafe = false - -# Maximum number of simultaneous connections (including WebSocket). -# Does not include gRPC connections. See grpc_max_open_connections -# If you want to accept a larger number than the default, make sure -# you increase your OS limits. -# 0 - unlimited. -# Should be < {ulimit -Sn} - {MaxNumInboundPeers} - {MaxNumOutboundPeers} - {N of wal, db and other open files} -# 1024 - 40 - 10 - 50 = 924 = ~900 -max_open_connections = 900 - -# How long to wait for a tx to be committed during /broadcast_tx_commit. -# WARNING: Using a value larger than 10s will result in increasing the -# global HTTP write timeout, which applies to all connections and endpoints. -# See https://github.com/tendermint/classic/issues/3435 -timeout_broadcast_tx_commit = "10s" - -# Maximum size of request body, in bytes -max_body_bytes = 1000000 - -# Maximum size of request header, in bytes -max_header_bytes = 1048576 - -# The path to a file containing certificate that is used to create the HTTPS server. -# Migth be either absolute path or path related to tendermint's config directory. -# If the certificate is signed by a certificate authority, -# the certFile should be the concatenation of the server's certificate, any intermediates, -# and the CA's certificate. -# NOTE: both tls_cert_file and tls_key_file must be present for Tendermint to create HTTPS server. Otherwise, HTTP server is run. -tls_cert_file = "" - -# The path to a file containing matching private key that is used to create the HTTPS server. -# Migth be either absolute path or path related to tendermint's config directory. -# NOTE: both tls_cert_file and tls_key_file must be present for Tendermint to create HTTPS server. Otherwise, HTTP server is run. -tls_key_file = "" - -##### peer to peer configuration options ##### -[p2p] - -# Address to listen for incoming connections -laddr = "tcp://0.0.0.0:36656" - -# Address to advertise to peers for them to dial -# If empty, will use the same port as the laddr, -# and will introspect on the listener or use UPnP -# to figure out the address. -external_address = "" - -# Comma separated list of seed nodes to connect to -seeds = "" - -# Comma separated list of nodes to keep persistent connections to -persistent_peers = "" - -# UPNP port forwarding -upnp = false - -# Maximum number of inbound peers -max_num_inbound_peers = 40 - -# Maximum number of outbound peers to connect to, excluding persistent peers -max_num_outbound_peers = 10 - -# Time to wait before flushing messages out on the connection -flush_throttle_timeout = "100ms" - -# Maximum size of a message packet payload, in bytes -max_packet_msg_payload_size = 1024 - -# Rate at which packets can be sent, in bytes/second -send_rate = 5120000 - -# Rate at which packets can be received, in bytes/second -recv_rate = 5120000 - -# Set true to enable the peer-exchange reactor -pex = true - -# Seed mode, in which node constantly crawls the network and looks for -# peers. If another node asks it for addresses, it responds and disconnects. -# -# Does not work if the peer-exchange reactor is disabled. -seed_mode = false - -# Comma separated list of peer IDs to keep private (will not be gossiped to other peers) -private_peer_ids = "" - -# Toggle to disable guard against peers connecting from the same ip. -allow_duplicate_ip = false - -# Peer connection configuration. -handshake_timeout = "20s" -dial_timeout = "3s" - -##### mempool configuration options ##### -[mempool] - -recheck = true -broadcast = true -wal_dir = "" - -# Maximum number of transactions in the mempool -size = 5000 - -# Limit the total size of all txs in the mempool. -# This only accounts for raw transactions (e.g. given 1MB transactions and -# max_txs_bytes=5MB, mempool will only accept 5 transactions). -max_pending_txs_bytes = 1073741824 - -# Size of the cache (used to filter transactions we saw earlier) in transactions -cache_size = 10000 - -##### consensus configuration options ##### -[consensus] - -wal_file = "data/cs.wal/wal" - -timeout_propose = "3s" -timeout_propose_delta = "500ms" -timeout_prevote = "1s" -timeout_prevote_delta = "500ms" -timeout_precommit = "1s" -timeout_precommit_delta = "500ms" -timeout_commit = "5s" - -# Make progress as soon as we have all the precommits (as if TimeoutCommit = 0) -skip_timeout_commit = false - -# EmptyBlocks mode and possible interval between empty blocks -create_empty_blocks = true -create_empty_blocks_interval = "0s" - -# Reactor sleep duration parameters -peer_gossip_sleep_duration = "100ms" -peer_query_maj23_sleep_duration = "2s" - diff --git a/util/gnolanddev/pull-1048-assertorigincall.diff b/util/gnolanddev/pull-1048-assertorigincall.diff deleted file mode 100644 index 4a87e20f..00000000 --- a/util/gnolanddev/pull-1048-assertorigincall.diff +++ /dev/null @@ -1,1964 +0,0 @@ -diff --git a/examples/gno.land/r/demo/boards/z_0_a_filetest.gno b/examples/gno.land/r/demo/boards/z_0_a_filetest.gno -index 872d01dd79..ae1724dd86 100644 ---- a/examples/gno.land/r/demo/boards/z_0_a_filetest.gno -+++ b/examples/gno.land/r/demo/boards/z_0_a_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/boards_test --package boards_test -+package main - - import ( - "gno.land/r/demo/boards" -diff --git a/examples/gno.land/r/demo/boards/z_0_b_filetest.gno b/examples/gno.land/r/demo/boards/z_0_b_filetest.gno -index 9ada8abd0c..70f040eb7b 100644 ---- a/examples/gno.land/r/demo/boards/z_0_b_filetest.gno -+++ b/examples/gno.land/r/demo/boards/z_0_b_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/boards_test --package boards_test -+package main - - // SEND: 199000000ugnot - -diff --git a/examples/gno.land/r/demo/boards/z_0_c_filetest.gno b/examples/gno.land/r/demo/boards/z_0_c_filetest.gno -index 36b7bcfda0..216e4e4397 100644 ---- a/examples/gno.land/r/demo/boards/z_0_c_filetest.gno -+++ b/examples/gno.land/r/demo/boards/z_0_c_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/boards_test --package boards_test -+package main - - // SEND: 200000000ugnot - -diff --git a/examples/gno.land/r/demo/boards/z_0_d_filetest.gno b/examples/gno.land/r/demo/boards/z_0_d_filetest.gno -index 2e9e3f1436..9539a9769a 100644 ---- a/examples/gno.land/r/demo/boards/z_0_d_filetest.gno -+++ b/examples/gno.land/r/demo/boards/z_0_d_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/boards_test --package boards_test -+package main - - // SEND: 200000000ugnot - -diff --git a/examples/gno.land/r/demo/boards/z_0_e_filetest.gno b/examples/gno.land/r/demo/boards/z_0_e_filetest.gno -index a06713fcbe..3411891f46 100644 ---- a/examples/gno.land/r/demo/boards/z_0_e_filetest.gno -+++ b/examples/gno.land/r/demo/boards/z_0_e_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/boards_test --package boards_test -+package main - - // SEND: 200000000ugnot - -diff --git a/examples/gno.land/r/demo/boards/z_0_filetest.gno b/examples/gno.land/r/demo/boards/z_0_filetest.gno -index 5c3fc7b204..801231b67e 100644 ---- a/examples/gno.land/r/demo/boards/z_0_filetest.gno -+++ b/examples/gno.land/r/demo/boards/z_0_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/boards_test --package boards_test -+package main - - // SEND: 200000000ugnot - -diff --git a/examples/gno.land/r/demo/boards/z_10_a_filetest.gno b/examples/gno.land/r/demo/boards/z_10_a_filetest.gno -index 8ec2e45421..02abd7dc14 100644 ---- a/examples/gno.land/r/demo/boards/z_10_a_filetest.gno -+++ b/examples/gno.land/r/demo/boards/z_10_a_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/boards_test --package boards_test -+package main - - // SEND: 200000000ugnot - -diff --git a/examples/gno.land/r/demo/boards/z_10_b_filetest.gno b/examples/gno.land/r/demo/boards/z_10_b_filetest.gno -index 0981d85a57..45a06ccc04 100644 ---- a/examples/gno.land/r/demo/boards/z_10_b_filetest.gno -+++ b/examples/gno.land/r/demo/boards/z_10_b_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/boards_test --package boards_test -+package main - - // SEND: 2000000000ugnot - -diff --git a/examples/gno.land/r/demo/boards/z_10_c_filetest.gno b/examples/gno.land/r/demo/boards/z_10_c_filetest.gno -index f161c8cede..7f2a180b01 100644 ---- a/examples/gno.land/r/demo/boards/z_10_c_filetest.gno -+++ b/examples/gno.land/r/demo/boards/z_10_c_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/boards_test --package boards_test -+package main - - // SEND: 200000000ugnot - -diff --git a/examples/gno.land/r/demo/boards/z_10_filetest.gno b/examples/gno.land/r/demo/boards/z_10_filetest.gno -index 7a24efe09c..6f9264d8db 100644 ---- a/examples/gno.land/r/demo/boards/z_10_filetest.gno -+++ b/examples/gno.land/r/demo/boards/z_10_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/boards_test --package boards_test -+package main - - // SEND: 200000000ugnot - -diff --git a/examples/gno.land/r/demo/boards/z_11_a_filetest.gno b/examples/gno.land/r/demo/boards/z_11_a_filetest.gno -index fd62a884ef..65edb0ddee 100644 ---- a/examples/gno.land/r/demo/boards/z_11_a_filetest.gno -+++ b/examples/gno.land/r/demo/boards/z_11_a_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/boards_test --package boards_test -+package main - - // SEND: 2000000000ugnot - -diff --git a/examples/gno.land/r/demo/boards/z_11_b_filetest.gno b/examples/gno.land/r/demo/boards/z_11_b_filetest.gno -index 63907146f8..f1547e085d 100644 ---- a/examples/gno.land/r/demo/boards/z_11_b_filetest.gno -+++ b/examples/gno.land/r/demo/boards/z_11_b_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/boards_test --package boards_test -+package main - - // SEND: 2000000000ugnot - -diff --git a/examples/gno.land/r/demo/boards/z_11_c_filetest.gno b/examples/gno.land/r/demo/boards/z_11_c_filetest.gno -index ba40fa3902..9bec2d5844 100644 ---- a/examples/gno.land/r/demo/boards/z_11_c_filetest.gno -+++ b/examples/gno.land/r/demo/boards/z_11_c_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/boards_test --package boards_test -+package main - - // SEND: 2000000000ugnot - -diff --git a/examples/gno.land/r/demo/boards/z_11_d_filetest.gno b/examples/gno.land/r/demo/boards/z_11_d_filetest.gno -index a519d4f6a9..7c4abfa36c 100644 ---- a/examples/gno.land/r/demo/boards/z_11_d_filetest.gno -+++ b/examples/gno.land/r/demo/boards/z_11_d_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/boards_test --package boards_test -+package main - - // SEND: 2000000000ugnot - -diff --git a/examples/gno.land/r/demo/boards/z_11_filetest.gno b/examples/gno.land/r/demo/boards/z_11_filetest.gno -index 2d96d46dc9..d38b0223cd 100644 ---- a/examples/gno.land/r/demo/boards/z_11_filetest.gno -+++ b/examples/gno.land/r/demo/boards/z_11_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/boards_test --package boards_test -+package main - - // SEND: 2000000000ugnot - -diff --git a/examples/gno.land/r/demo/boards/z_1_filetest.gno b/examples/gno.land/r/demo/boards/z_1_filetest.gno -index b5c7bb863e..13bea83ae4 100644 ---- a/examples/gno.land/r/demo/boards/z_1_filetest.gno -+++ b/examples/gno.land/r/demo/boards/z_1_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/boards_test --package boards_test -+package main - - // SEND: 200000000ugnot - -diff --git a/examples/gno.land/r/demo/boards/z_2_filetest.gno b/examples/gno.land/r/demo/boards/z_2_filetest.gno -index 1e0b55a395..547757ef0a 100644 ---- a/examples/gno.land/r/demo/boards/z_2_filetest.gno -+++ b/examples/gno.land/r/demo/boards/z_2_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/boards_test --package boards_test -+package main - - // SEND: 200000000ugnot - -diff --git a/examples/gno.land/r/demo/boards/z_3_filetest.gno b/examples/gno.land/r/demo/boards/z_3_filetest.gno -index f4160e1612..757f9430c6 100644 ---- a/examples/gno.land/r/demo/boards/z_3_filetest.gno -+++ b/examples/gno.land/r/demo/boards/z_3_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/boards_test --package boards_test -+package main - - // SEND: 200000000ugnot - -diff --git a/examples/gno.land/r/demo/boards/z_4_filetest.gno b/examples/gno.land/r/demo/boards/z_4_filetest.gno -index 749566ea5b..68b1955ae3 100644 ---- a/examples/gno.land/r/demo/boards/z_4_filetest.gno -+++ b/examples/gno.land/r/demo/boards/z_4_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/boards_test --package boards_test -+package main - - // SEND: 200000000ugnot - -@@ -44,929 +43,3 @@ func main() { - // - // > Second reply of the second post - // > \- [@gnouser](/r/users:gnouser), [2009-02-13 11:31pm (UTC)](/r/demo/boards:test_board/2/4) \[[reply](/r/demo/boards?help&__func=CreateReply&bid=1&threadid=2&postid=4&body.type=textarea)] \[[x](/r/demo/boards?help&__func=DeletePost&bid=1&threadid=2&postid=4)] -- --// Realm: --// switchrealm["gno.land/r/demo/users"] --// switchrealm["gno.land/r/demo/users"] --// switchrealm["gno.land/r/demo/boards"] --// u[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:101]={ --// "Fields": [ --// { --// "T": { --// "@type": "/gno.PrimitiveType", --// "value": "16" --// }, --// "V": { --// "@type": "/gno.StringValue", --// "value": "0000000003" --// } --// }, --// { --// "T": { --// "@type": "/gno.PointerType", --// "Elt": { --// "@type": "/gno.RefType", --// "ID": "gno.land/r/demo/boards.Post" --// } --// }, --// "V": { --// "@type": "/gno.PointerValue", --// "Base": null, --// "Index": "0", --// "TV": { --// "T": { --// "@type": "/gno.RefType", --// "ID": "gno.land/r/demo/boards.Post" --// }, --// "V": { --// "@type": "/gno.RefValue", --// "Escaped": true, --// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:102" --// } --// } --// } --// }, --// { --// "T": { --// "@type": "/gno.PrimitiveType", --// "value": "64" --// } --// }, --// { --// "N": "AQAAAAAAAAA=", --// "T": { --// "@type": "/gno.PrimitiveType", --// "value": "32" --// } --// }, --// { --// "T": { --// "@type": "/gno.PointerType", --// "Elt": { --// "@type": "/gno.RefType", --// "ID": "gno.land/p/demo/avl.Node" --// } --// } --// }, --// { --// "T": { --// "@type": "/gno.PointerType", --// "Elt": { --// "@type": "/gno.RefType", --// "ID": "gno.land/p/demo/avl.Node" --// } --// } --// } --// ], --// "ObjectInfo": { --// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:101", --// "ModTime": "109", --// "OwnerID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:109", --// "RefCount": "1" --// } --// } --// c[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:110]={ --// "Fields": [ --// { --// "T": { --// "@type": "/gno.PrimitiveType", --// "value": "16" --// }, --// "V": { --// "@type": "/gno.StringValue", --// "value": "0000000004" --// } --// }, --// { --// "T": { --// "@type": "/gno.PointerType", --// "Elt": { --// "@type": "/gno.RefType", --// "ID": "gno.land/r/demo/boards.Post" --// } --// }, --// "V": { --// "@type": "/gno.PointerValue", --// "Base": null, --// "Index": "0", --// "TV": { --// "T": { --// "@type": "/gno.RefType", --// "ID": "gno.land/r/demo/boards.Post" --// }, --// "V": { --// "@type": "/gno.RefValue", --// "Escaped": true, --// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:111" --// } --// } --// } --// }, --// { --// "T": { --// "@type": "/gno.PrimitiveType", --// "value": "64" --// } --// }, --// { --// "N": "AQAAAAAAAAA=", --// "T": { --// "@type": "/gno.PrimitiveType", --// "value": "32" --// } --// }, --// { --// "T": { --// "@type": "/gno.PointerType", --// "Elt": { --// "@type": "/gno.RefType", --// "ID": "gno.land/p/demo/avl.Node" --// } --// } --// }, --// { --// "T": { --// "@type": "/gno.PointerType", --// "Elt": { --// "@type": "/gno.RefType", --// "ID": "gno.land/p/demo/avl.Node" --// } --// } --// } --// ], --// "ObjectInfo": { --// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:110", --// "ModTime": "0", --// "OwnerID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:109", --// "RefCount": "1" --// } --// } --// c[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:109]={ --// "Fields": [ --// { --// "T": { --// "@type": "/gno.PrimitiveType", --// "value": "16" --// }, --// "V": { --// "@type": "/gno.StringValue", --// "value": "0000000004" --// } --// }, --// {}, --// { --// "N": "AQAAAAAAAAA=", --// "T": { --// "@type": "/gno.PrimitiveType", --// "value": "64" --// } --// }, --// { --// "N": "AgAAAAAAAAA=", --// "T": { --// "@type": "/gno.PrimitiveType", --// "value": "32" --// } --// }, --// { --// "T": { --// "@type": "/gno.PointerType", --// "Elt": { --// "@type": "/gno.RefType", --// "ID": "gno.land/p/demo/avl.Node" --// } --// }, --// "V": { --// "@type": "/gno.PointerValue", --// "Base": null, --// "Index": "0", --// "TV": { --// "T": { --// "@type": "/gno.RefType", --// "ID": "gno.land/p/demo/avl.Node" --// }, --// "V": { --// "@type": "/gno.RefValue", --// "Hash": "b58581159917d8d7ad0992009d7184fc8ca00fcc", --// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:101" --// } --// } --// } --// }, --// { --// "T": { --// "@type": "/gno.PointerType", --// "Elt": { --// "@type": "/gno.RefType", --// "ID": "gno.land/p/demo/avl.Node" --// } --// }, --// "V": { --// "@type": "/gno.PointerValue", --// "Base": null, --// "Index": "0", --// "TV": { --// "T": { --// "@type": "/gno.RefType", --// "ID": "gno.land/p/demo/avl.Node" --// }, --// "V": { --// "@type": "/gno.RefValue", --// "Hash": "fb593e86d35aaf607e0d21e6bd4f84519c44585f", --// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:110" --// } --// } --// } --// } --// ], --// "ObjectInfo": { --// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:109", --// "ModTime": "0", --// "OwnerID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:96", --// "RefCount": "1" --// } --// } --// c[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:112]={ --// "Fields": [ --// { --// "T": { --// "@type": "/gno.PointerType", --// "Elt": { --// "@type": "/gno.RefType", --// "ID": "gno.land/p/demo/avl.Node" --// } --// } --// } --// ], --// "ObjectInfo": { --// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:112", --// "ModTime": "0", --// "OwnerID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:111", --// "RefCount": "1" --// } --// } --// c[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:113]={ --// "Fields": [ --// { --// "T": { --// "@type": "/gno.PointerType", --// "Elt": { --// "@type": "/gno.RefType", --// "ID": "gno.land/p/demo/avl.Node" --// } --// } --// } --// ], --// "ObjectInfo": { --// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:113", --// "ModTime": "0", --// "OwnerID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:111", --// "RefCount": "1" --// } --// } --// c[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:114]={ --// "Fields": [ --// { --// "T": { --// "@type": "/gno.PointerType", --// "Elt": { --// "@type": "/gno.RefType", --// "ID": "gno.land/p/demo/avl.Node" --// } --// } --// } --// ], --// "ObjectInfo": { --// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:114", --// "ModTime": "0", --// "OwnerID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:111", --// "RefCount": "1" --// } --// } --// c[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:115]={ --// "Fields": [ --// { --// "N": "AAAAgJSeXbo=", --// "T": { --// "@type": "/gno.PrimitiveType", --// "value": "65536" --// } --// }, --// { --// "N": "AbSNdvQQIhE=", --// "T": { --// "@type": "/gno.PrimitiveType", --// "value": "1024" --// } --// }, --// { --// "T": { --// "@type": "/gno.PointerType", --// "Elt": { --// "@type": "/gno.RefType", --// "ID": "time.Location" --// } --// }, --// "V": { --// "@type": "/gno.PointerValue", --// "Base": { --// "@type": "/gno.RefValue", --// "Escaped": true, --// "ObjectID": "336074805fc853987abe6f7fe3ad97a6a6f3077a:2" --// }, --// "Index": "188", --// "TV": null --// } --// } --// ], --// "ObjectInfo": { --// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:115", --// "ModTime": "0", --// "OwnerID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:111", --// "RefCount": "1" --// } --// } --// c[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:116]={ --// "Fields": [ --// { --// "T": { --// "@type": "/gno.PrimitiveType", --// "value": "65536" --// } --// }, --// { --// "T": { --// "@type": "/gno.PrimitiveType", --// "value": "1024" --// } --// }, --// { --// "T": { --// "@type": "/gno.PointerType", --// "Elt": { --// "@type": "/gno.RefType", --// "ID": "time.Location" --// } --// } --// } --// ], --// "ObjectInfo": { --// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:116", --// "ModTime": "0", --// "OwnerID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:111", --// "RefCount": "1" --// } --// } --// c[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:111]={ --// "Fields": [ --// { --// "T": { --// "@type": "/gno.PointerType", --// "Elt": { --// "@type": "/gno.RefType", --// "ID": "gno.land/r/demo/boards.Board" --// } --// }, --// "V": { --// "@type": "/gno.PointerValue", --// "Base": null, --// "Index": "0", --// "TV": { --// "T": { --// "@type": "/gno.RefType", --// "ID": "gno.land/r/demo/boards.Board" --// }, --// "V": { --// "@type": "/gno.RefValue", --// "Escaped": true, --// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:81" --// } --// } --// } --// }, --// { --// "N": "BAAAAAAAAAA=", --// "T": { --// "@type": "/gno.RefType", --// "ID": "gno.land/r/demo/boards.PostID" --// } --// }, --// { --// "T": { --// "@type": "/gno.RefType", --// "ID": "std.Address" --// }, --// "V": { --// "@type": "/gno.StringValue", --// "value": "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" --// } --// }, --// { --// "T": { --// "@type": "/gno.PrimitiveType", --// "value": "16" --// }, --// "V": { --// "@type": "/gno.StringValue", --// "value": "" --// } --// }, --// { --// "T": { --// "@type": "/gno.PrimitiveType", --// "value": "16" --// }, --// "V": { --// "@type": "/gno.StringValue", --// "value": "Second reply of the second post" --// } --// }, --// { --// "T": { --// "@type": "/gno.RefType", --// "ID": "gno.land/p/demo/avl.Tree" --// }, --// "V": { --// "@type": "/gno.RefValue", --// "Hash": "130542396d7549d1d516a3ef4a63bb44ef3da06f", --// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:112" --// } --// }, --// { --// "T": { --// "@type": "/gno.RefType", --// "ID": "gno.land/p/demo/avl.Tree" --// }, --// "V": { --// "@type": "/gno.RefValue", --// "Hash": "80acd8746478317194b8546170335c796a4dfb3f", --// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:113" --// } --// }, --// { --// "T": { --// "@type": "/gno.RefType", --// "ID": "gno.land/p/demo/avl.Tree" --// }, --// "V": { --// "@type": "/gno.RefValue", --// "Hash": "c1a8f769f3b9d52dd38ac4759116edaca287636f", --// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:114" --// } --// }, --// { --// "N": "AgAAAAAAAAA=", --// "T": { --// "@type": "/gno.RefType", --// "ID": "gno.land/r/demo/boards.PostID" --// } --// }, --// { --// "N": "AgAAAAAAAAA=", --// "T": { --// "@type": "/gno.RefType", --// "ID": "gno.land/r/demo/boards.PostID" --// } --// }, --// { --// "T": { --// "@type": "/gno.RefType", --// "ID": "gno.land/r/demo/boards.BoardID" --// } --// }, --// { --// "T": { --// "@type": "/gno.RefType", --// "ID": "time.Time" --// }, --// "V": { --// "@type": "/gno.RefValue", --// "Hash": "8164abed5231309c88497013f7da72a1b5d427b0", --// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:115" --// } --// }, --// { --// "T": { --// "@type": "/gno.RefType", --// "ID": "time.Time" --// }, --// "V": { --// "@type": "/gno.RefValue", --// "Hash": "c3a60b602b564d07677a212372f4ac1cae4270fd", --// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:116" --// } --// } --// ], --// "ObjectInfo": { --// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:111", --// "IsEscaped": true, --// "ModTime": "0", --// "RefCount": "2" --// } --// } --// u[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:108]={ --// "Fields": [ --// { --// "T": { --// "@type": "/gno.PrimitiveType", --// "value": "16" --// }, --// "V": { --// "@type": "/gno.StringValue", --// "value": "0000000003" --// } --// }, --// { --// "T": { --// "@type": "/gno.PointerType", --// "Elt": { --// "@type": "/gno.RefType", --// "ID": "gno.land/r/demo/boards.Post" --// } --// }, --// "V": { --// "@type": "/gno.PointerValue", --// "Base": null, --// "Index": "0", --// "TV": { --// "T": { --// "@type": "/gno.RefType", --// "ID": "gno.land/r/demo/boards.Post" --// }, --// "V": { --// "@type": "/gno.RefValue", --// "Escaped": true, --// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:102" --// } --// } --// } --// }, --// { --// "T": { --// "@type": "/gno.PrimitiveType", --// "value": "64" --// } --// }, --// { --// "N": "AQAAAAAAAAA=", --// "T": { --// "@type": "/gno.PrimitiveType", --// "value": "32" --// } --// }, --// { --// "T": { --// "@type": "/gno.PointerType", --// "Elt": { --// "@type": "/gno.RefType", --// "ID": "gno.land/p/demo/avl.Node" --// } --// } --// }, --// { --// "T": { --// "@type": "/gno.PointerType", --// "Elt": { --// "@type": "/gno.RefType", --// "ID": "gno.land/p/demo/avl.Node" --// } --// } --// } --// ], --// "ObjectInfo": { --// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:108", --// "ModTime": "117", --// "OwnerID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:117", --// "RefCount": "1" --// } --// } --// c[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:118]={ --// "Fields": [ --// { --// "T": { --// "@type": "/gno.PrimitiveType", --// "value": "16" --// }, --// "V": { --// "@type": "/gno.StringValue", --// "value": "0000000004" --// } --// }, --// { --// "T": { --// "@type": "/gno.PointerType", --// "Elt": { --// "@type": "/gno.RefType", --// "ID": "gno.land/r/demo/boards.Post" --// } --// }, --// "V": { --// "@type": "/gno.PointerValue", --// "Base": null, --// "Index": "0", --// "TV": { --// "T": { --// "@type": "/gno.RefType", --// "ID": "gno.land/r/demo/boards.Post" --// }, --// "V": { --// "@type": "/gno.RefValue", --// "Escaped": true, --// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:111" --// } --// } --// } --// }, --// { --// "T": { --// "@type": "/gno.PrimitiveType", --// "value": "64" --// } --// }, --// { --// "N": "AQAAAAAAAAA=", --// "T": { --// "@type": "/gno.PrimitiveType", --// "value": "32" --// } --// }, --// { --// "T": { --// "@type": "/gno.PointerType", --// "Elt": { --// "@type": "/gno.RefType", --// "ID": "gno.land/p/demo/avl.Node" --// } --// } --// }, --// { --// "T": { --// "@type": "/gno.PointerType", --// "Elt": { --// "@type": "/gno.RefType", --// "ID": "gno.land/p/demo/avl.Node" --// } --// } --// } --// ], --// "ObjectInfo": { --// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:118", --// "ModTime": "0", --// "OwnerID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:117", --// "RefCount": "1" --// } --// } --// c[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:117]={ --// "Fields": [ --// { --// "T": { --// "@type": "/gno.PrimitiveType", --// "value": "16" --// }, --// "V": { --// "@type": "/gno.StringValue", --// "value": "0000000004" --// } --// }, --// {}, --// { --// "N": "AQAAAAAAAAA=", --// "T": { --// "@type": "/gno.PrimitiveType", --// "value": "64" --// } --// }, --// { --// "N": "AgAAAAAAAAA=", --// "T": { --// "@type": "/gno.PrimitiveType", --// "value": "32" --// } --// }, --// { --// "T": { --// "@type": "/gno.PointerType", --// "Elt": { --// "@type": "/gno.RefType", --// "ID": "gno.land/p/demo/avl.Node" --// } --// }, --// "V": { --// "@type": "/gno.PointerValue", --// "Base": null, --// "Index": "0", --// "TV": { --// "T": { --// "@type": "/gno.RefType", --// "ID": "gno.land/p/demo/avl.Node" --// }, --// "V": { --// "@type": "/gno.RefValue", --// "Hash": "6a86bc7763703c8f2b9d286368921159d6db121c", --// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:108" --// } --// } --// } --// }, --// { --// "T": { --// "@type": "/gno.PointerType", --// "Elt": { --// "@type": "/gno.RefType", --// "ID": "gno.land/p/demo/avl.Node" --// } --// }, --// "V": { --// "@type": "/gno.PointerValue", --// "Base": null, --// "Index": "0", --// "TV": { --// "T": { --// "@type": "/gno.RefType", --// "ID": "gno.land/p/demo/avl.Node" --// }, --// "V": { --// "@type": "/gno.RefValue", --// "Hash": "52faa8a2dfefd4b6b6249eff2f9c123ad455e81d", --// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:118" --// } --// } --// } --// } --// ], --// "ObjectInfo": { --// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:117", --// "ModTime": "0", --// "OwnerID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:97", --// "RefCount": "1" --// } --// } --// u[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:81]={ --// "Fields": [ --// { --// "N": "AQAAAAAAAAA=", --// "T": { --// "@type": "/gno.RefType", --// "ID": "gno.land/r/demo/boards.BoardID" --// } --// }, --// { --// "T": { --// "@type": "/gno.PrimitiveType", --// "value": "16" --// }, --// "V": { --// "@type": "/gno.StringValue", --// "value": "/r/demo/boards:test_board" --// } --// }, --// { --// "T": { --// "@type": "/gno.PrimitiveType", --// "value": "16" --// }, --// "V": { --// "@type": "/gno.StringValue", --// "value": "test_board" --// } --// }, --// { --// "T": { --// "@type": "/gno.RefType", --// "ID": "std.Address" --// }, --// "V": { --// "@type": "/gno.StringValue", --// "value": "g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm" --// } --// }, --// { --// "T": { --// "@type": "/gno.RefType", --// "ID": "gno.land/p/demo/avl.Tree" --// }, --// "V": { --// "@type": "/gno.RefValue", --// "Hash": "5b4b593f1d4b37cb99166247ea28174f91087fdd", --// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:82" --// } --// }, --// { --// "N": "BAAAAAAAAAA=", --// "T": { --// "@type": "/gno.PrimitiveType", --// "value": "65536" --// } --// }, --// { --// "T": { --// "@type": "/gno.RefType", --// "ID": "time.Time" --// }, --// "V": { --// "@type": "/gno.RefValue", --// "Hash": "7e9fd9bb5e90a06c7751585cd80f23aedddde25b", --// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:83" --// } --// }, --// { --// "T": { --// "@type": "/gno.RefType", --// "ID": "gno.land/p/demo/avl.Tree" --// }, --// "V": { --// "@type": "/gno.RefValue", --// "Hash": "edb1857302fa916c562cd077cdf2a3626e29ae2b", --// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:84" --// } --// } --// ], --// "ObjectInfo": { --// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:81", --// "IsEscaped": true, --// "ModTime": "108", --// "RefCount": "6" --// } --// } --// u[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:96]={ --// "Fields": [ --// { --// "T": { --// "@type": "/gno.PointerType", --// "Elt": { --// "@type": "/gno.RefType", --// "ID": "gno.land/p/demo/avl.Node" --// } --// }, --// "V": { --// "@type": "/gno.PointerValue", --// "Base": null, --// "Index": "0", --// "TV": { --// "T": { --// "@type": "/gno.RefType", --// "ID": "gno.land/p/demo/avl.Node" --// }, --// "V": { --// "@type": "/gno.RefValue", --// "Hash": "609e7f519c65f94503427a14f973b4b83989cdc8", --// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:109" --// } --// } --// } --// } --// ], --// "ObjectInfo": { --// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:96", --// "ModTime": "108", --// "OwnerID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:95", --// "RefCount": "1" --// } --// } --// u[f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:97]={ --// "Fields": [ --// { --// "T": { --// "@type": "/gno.PointerType", --// "Elt": { --// "@type": "/gno.RefType", --// "ID": "gno.land/p/demo/avl.Node" --// } --// }, --// "V": { --// "@type": "/gno.PointerValue", --// "Base": null, --// "Index": "0", --// "TV": { --// "T": { --// "@type": "/gno.RefType", --// "ID": "gno.land/p/demo/avl.Node" --// }, --// "V": { --// "@type": "/gno.RefValue", --// "Hash": "6760340f5b40e05221dc530940683b0b9a422503", --// "ObjectID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:117" --// } --// } --// } --// } --// ], --// "ObjectInfo": { --// "ID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:97", --// "ModTime": "108", --// "OwnerID": "f6dbf411da22e67d74cd7ddba6a76cd7e14a4822:95", --// "RefCount": "1" --// } --// } --// switchrealm["gno.land/r/demo/boards"] --// switchrealm["gno.land/r/demo/users"] --// switchrealm["gno.land/r/demo/users"] --// switchrealm["gno.land/r/demo/users"] --// switchrealm["gno.land/r/demo/users"] --// switchrealm["gno.land/r/demo/users"] --// switchrealm["gno.land/r/demo/users"] --// switchrealm["gno.land/r/demo/users"] --// switchrealm["gno.land/r/demo/users"] --// switchrealm["gno.land/r/demo/users"] --// switchrealm["gno.land/r/demo/boards"] --// switchrealm["gno.land/r/boards_test"] -diff --git a/examples/gno.land/r/demo/boards/z_5_filetest.gno b/examples/gno.land/r/demo/boards/z_5_filetest.gno -index 421d944078..d9ebf69e0d 100644 ---- a/examples/gno.land/r/demo/boards/z_5_filetest.gno -+++ b/examples/gno.land/r/demo/boards/z_5_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/boards_test --package boards_test -+package main - - // SEND: 200000000ugnot - -diff --git a/examples/gno.land/r/demo/boards/z_6_filetest.gno b/examples/gno.land/r/demo/boards/z_6_filetest.gno -index 2a392808d3..6647848894 100644 ---- a/examples/gno.land/r/demo/boards/z_6_filetest.gno -+++ b/examples/gno.land/r/demo/boards/z_6_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/boards_test --package boards_test -+package main - - // SEND: 200000000ugnot - -diff --git a/examples/gno.land/r/demo/boards/z_7_filetest.gno b/examples/gno.land/r/demo/boards/z_7_filetest.gno -index 1294f72c1b..bb46372ec7 100644 ---- a/examples/gno.land/r/demo/boards/z_7_filetest.gno -+++ b/examples/gno.land/r/demo/boards/z_7_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/boards_test --package boards_test -+package main - - // SEND: 2000000000ugnot - -diff --git a/examples/gno.land/r/demo/boards/z_8_filetest.gno b/examples/gno.land/r/demo/boards/z_8_filetest.gno -index 5ba0b34ad3..c4e6c33643 100644 ---- a/examples/gno.land/r/demo/boards/z_8_filetest.gno -+++ b/examples/gno.land/r/demo/boards/z_8_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/boards_test --package boards_test -+package main - - // SEND: 2000000000ugnot - -diff --git a/examples/gno.land/r/demo/boards/z_9_a_filetest.gno b/examples/gno.land/r/demo/boards/z_9_a_filetest.gno -index 9ba9786c51..351235fba3 100644 ---- a/examples/gno.land/r/demo/boards/z_9_a_filetest.gno -+++ b/examples/gno.land/r/demo/boards/z_9_a_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/boards_test --package boards_test -+package main - - // SEND: 200000000ugnot - -diff --git a/examples/gno.land/r/demo/boards/z_9_b_filetest.gno b/examples/gno.land/r/demo/boards/z_9_b_filetest.gno -index 4d53f60f10..7715456564 100644 ---- a/examples/gno.land/r/demo/boards/z_9_b_filetest.gno -+++ b/examples/gno.land/r/demo/boards/z_9_b_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/boards_test --package boards_test -+package main - - // SEND: 200000000ugnot - -diff --git a/examples/gno.land/r/demo/boards/z_9_filetest.gno b/examples/gno.land/r/demo/boards/z_9_filetest.gno -index 66f8950732..7461a3b67c 100644 ---- a/examples/gno.land/r/demo/boards/z_9_filetest.gno -+++ b/examples/gno.land/r/demo/boards/z_9_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/boards_test --package boards_test -+package main - - // SEND: 200000000ugnot - -diff --git a/examples/gno.land/r/demo/groups/z_0_a_filetest.gno b/examples/gno.land/r/demo/groups/z_0_a_filetest.gno -index 41d515b9d0..95c5c2d0e6 100644 ---- a/examples/gno.land/r/demo/groups/z_0_a_filetest.gno -+++ b/examples/gno.land/r/demo/groups/z_0_a_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/groups_test --package groups_test -+package main - - import ( - "gno.land/r/demo/groups" -diff --git a/examples/gno.land/r/demo/groups/z_0_b_filetest.gno b/examples/gno.land/r/demo/groups/z_0_b_filetest.gno -index ca74c59913..047a5915bb 100644 ---- a/examples/gno.land/r/demo/groups/z_0_b_filetest.gno -+++ b/examples/gno.land/r/demo/groups/z_0_b_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/groups_test --package groups_test -+package main - - import ( - "gno.land/r/demo/groups" -diff --git a/examples/gno.land/r/demo/groups/z_0_c_filetest.gno b/examples/gno.land/r/demo/groups/z_0_c_filetest.gno -index 10a4771c52..92fc412374 100644 ---- a/examples/gno.land/r/demo/groups/z_0_c_filetest.gno -+++ b/examples/gno.land/r/demo/groups/z_0_c_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/groups_test --package groups_test -+package main - - // SEND: 200000000ugnot - -diff --git a/examples/gno.land/r/demo/groups/z_1_a_filetest.gno b/examples/gno.land/r/demo/groups/z_1_a_filetest.gno -index 460fb79afb..8a957f1de1 100644 ---- a/examples/gno.land/r/demo/groups/z_1_a_filetest.gno -+++ b/examples/gno.land/r/demo/groups/z_1_a_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/groups_test --package groups_test -+package main - - // SEND: 200000000ugnot - -diff --git a/examples/gno.land/r/demo/groups/z_1_b_filetest.gno b/examples/gno.land/r/demo/groups/z_1_b_filetest.gno -index 3271e74e28..99ed8e39b1 100644 ---- a/examples/gno.land/r/demo/groups/z_1_b_filetest.gno -+++ b/examples/gno.land/r/demo/groups/z_1_b_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/groups_test --package groups_test -+package main - - // SEND: 200000000ugnot - -diff --git a/examples/gno.land/r/demo/groups/z_1_c_filetest.gno b/examples/gno.land/r/demo/groups/z_1_c_filetest.gno -index 93cd3b39d5..e2988c7d9d 100644 ---- a/examples/gno.land/r/demo/groups/z_1_c_filetest.gno -+++ b/examples/gno.land/r/demo/groups/z_1_c_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/groups_test --package groups_test -+package main - - // SEND: 200000000ugnot - -diff --git a/examples/gno.land/r/demo/groups/z_2_a_filetest.gno b/examples/gno.land/r/demo/groups/z_2_a_filetest.gno -index f4a96905fc..7136ae0433 100644 ---- a/examples/gno.land/r/demo/groups/z_2_a_filetest.gno -+++ b/examples/gno.land/r/demo/groups/z_2_a_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/groups_test --package groups_test -+package main - - // SEND: 200000000ugnot - -diff --git a/examples/gno.land/r/demo/groups/z_2_b_filetest.gno b/examples/gno.land/r/demo/groups/z_2_b_filetest.gno -index bf10939c66..5614c8039b 100644 ---- a/examples/gno.land/r/demo/groups/z_2_b_filetest.gno -+++ b/examples/gno.land/r/demo/groups/z_2_b_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/groups_test --package groups_test -+package main - - // SEND: 200000000ugnot - -diff --git a/examples/gno.land/r/demo/groups/z_2_d_filetest.gno b/examples/gno.land/r/demo/groups/z_2_d_filetest.gno -index 95f22f4ec4..c45e6c3b2a 100644 ---- a/examples/gno.land/r/demo/groups/z_2_d_filetest.gno -+++ b/examples/gno.land/r/demo/groups/z_2_d_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/groups_test --package groups_test -+package main - - // SEND: 200000000ugnot - -diff --git a/examples/gno.land/r/demo/groups/z_2_e_filetest.gno b/examples/gno.land/r/demo/groups/z_2_e_filetest.gno -index 270ddb8aa3..6ebc4d8bbe 100644 ---- a/examples/gno.land/r/demo/groups/z_2_e_filetest.gno -+++ b/examples/gno.land/r/demo/groups/z_2_e_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/groups_test --package groups_test -+package main - - // SEND: 200000000ugnot - -diff --git a/examples/gno.land/r/demo/groups/z_2_f_filetest.gno b/examples/gno.land/r/demo/groups/z_2_f_filetest.gno -index 4ec0ec211f..9c51e31edf 100644 ---- a/examples/gno.land/r/demo/groups/z_2_f_filetest.gno -+++ b/examples/gno.land/r/demo/groups/z_2_f_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/groups_test --package groups_test -+package main - - // SEND: 200000000ugnot - -diff --git a/examples/gno.land/r/demo/groups/z_2_g_filetest.gno b/examples/gno.land/r/demo/groups/z_2_g_filetest.gno -index 8f98cfeb2d..cd5ebf62c8 100644 ---- a/examples/gno.land/r/demo/groups/z_2_g_filetest.gno -+++ b/examples/gno.land/r/demo/groups/z_2_g_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/groups_test --package groups_test -+package main - - // SEND: 200000000ugnot - -diff --git a/examples/gno.land/r/demo/tests/subtests/subtests.gno b/examples/gno.land/r/demo/tests/subtests/subtests.gno -index e8796a7308..5cc4d1bea1 100644 ---- a/examples/gno.land/r/demo/tests/subtests/subtests.gno -+++ b/examples/gno.land/r/demo/tests/subtests/subtests.gno -@@ -15,3 +15,11 @@ func GetPrevRealm() std.Realm { - func Exec(fn func()) { - fn() - } -+ -+func AssertOriginCall() { -+ std.AssertOriginCall() -+} -+ -+func IsOriginCall() bool { -+ return std.IsOriginCall() -+} -diff --git a/examples/gno.land/r/demo/tests/tests.gno b/examples/gno.land/r/demo/tests/tests.gno -index fb49b2273a..67ae4bc917 100644 ---- a/examples/gno.land/r/demo/tests/tests.gno -+++ b/examples/gno.land/r/demo/tests/tests.gno -@@ -28,6 +28,14 @@ func IsOriginCall() bool { - return std.IsOriginCall() - } - -+func RSubtestsAssertOriginCall() { -+ rsubtests.AssertOriginCall() -+} -+ -+func RSubtestsIsOriginCall() bool { -+ return rsubtests.IsOriginCall() -+} -+ - //---------------------------------------- - // Test structure to ensure cross-realm modification is prevented. - -diff --git a/examples/gno.land/r/demo/tests/tests_test.gno b/examples/gno.land/r/demo/tests/tests_test.gno -index 3dcbeecf18..3c92613d3d 100644 ---- a/examples/gno.land/r/demo/tests/tests_test.gno -+++ b/examples/gno.land/r/demo/tests/tests_test.gno -@@ -22,14 +22,10 @@ func TestAssertOriginCall(t *testing.T) { - t.Errorf("expected panic with '%v', got '%v'", expectedReason, r) - } - }() -- func() { -- // if called inside a function literal, this is no longer an origin call -- // because there's one additional frame (the function literal). -- if IsOriginCall() { -- t.Errorf("expected IsOriginCall=false but got true") -- } -- AssertOriginCall() -- }() -+ if RSubtestsIsOriginCall() { -+ t.Errorf("expected RSubtestsIsOriginCall=false but got true") -+ } -+ RSubtestsAssertOriginCall() - } - - func TestPrevRealm(t *testing.T) { -diff --git a/examples/gno.land/r/demo/tests/z0_filetest.gno b/examples/gno.land/r/demo/tests/z0_filetest.gno -index c4beb8e200..2f5ab9fa05 100644 ---- a/examples/gno.land/r/demo/tests/z0_filetest.gno -+++ b/examples/gno.land/r/demo/tests/z0_filetest.gno -@@ -9,16 +9,12 @@ func main() { - tests.AssertOriginCall() - println("AssertOriginCall doesn't panic when called directly") - -- func() { -- // if called inside a function literal, this is no longer an origin call -- // because there's one additional frame (the function literal). -- println("IsOriginCall:", tests.IsOriginCall()) -- defer func() { -- r := recover() -- println("AssertOriginCall panics if when called inside a function literal:", r) -- }() -- tests.AssertOriginCall() -+ println("IsOriginCall:", tests.RSubtestsIsOriginCall()) -+ defer func() { -+ r := recover() -+ println("AssertOriginCall panics if when called inside a function literal:", r) - }() -+ tests.RSubtestsAssertOriginCall() - } - - // Output: -diff --git a/examples/gno.land/r/demo/users/z_10_filetest.gno b/examples/gno.land/r/demo/users/z_10_filetest.gno -index 0065d907e4..607ced8e2d 100644 ---- a/examples/gno.land/r/demo/users/z_10_filetest.gno -+++ b/examples/gno.land/r/demo/users/z_10_filetest.gno -@@ -1,5 +1,4 @@ --// PKGPATH: gno.land/r/users_test --package users_test -+package main - - import ( - "std" -diff --git a/gnovm/stdlibs/frame.go b/gnovm/stdlibs/frame.go -index e428bb1776..a8c50ee6bf 100644 ---- a/gnovm/stdlibs/frame.go -+++ b/gnovm/stdlibs/frame.go -@@ -1,6 +1,9 @@ - package stdlibs - --import "github.com/gnolang/gno/tm2/pkg/crypto" -+import ( -+ gno "github.com/gnolang/gno/gnovm/pkg/gnolang" -+ "github.com/gnolang/gno/tm2/pkg/crypto" -+) - - type Realm struct { - addr crypto.Bech32Address -@@ -18,3 +21,39 @@ func (r Realm) PkgPath() string { - func (r Realm) IsUser() bool { - return r.pkgPath == "" - } -+ -+// isOriginCall returns true if the std.OrigCaller == std.PrevRealm -+func isOriginCall(m *gno.Machine) bool { -+ return prevRealm(m).addr == m.Context.(ExecContext).OrigCaller -+} -+ -+// prevRealm loops on frames and returns the second realm found in the calling -+// order. If no such realm was found, returns the tx signer (aka OrigCaller). -+func prevRealm(m *gno.Machine) Realm { -+ var lastRealmPath string -+ for i := m.NumFrames() - 1; i > 0; i-- { -+ fr := m.Frames[i] -+ if fr.LastPackage == nil || !fr.LastPackage.IsRealm() { -+ // Ignore non-realm frame -+ continue -+ } -+ realmPath := fr.LastPackage.PkgPath -+ if lastRealmPath == "" { -+ // Record the path of the first encountered realm and continue -+ lastRealmPath = realmPath -+ continue -+ } -+ if lastRealmPath != realmPath { -+ // Second realm detected, return it. -+ return Realm{ -+ addr: fr.LastPackage.GetPkgAddr().Bech32(), -+ pkgPath: realmPath, -+ } -+ } -+ } -+ // No second realm found, return the tx signer. -+ return Realm{ -+ addr: m.Context.(ExecContext).OrigCaller, -+ pkgPath: "", // empty for users -+ } -+} -diff --git a/gnovm/stdlibs/frame_test.go b/gnovm/stdlibs/frame_test.go -new file mode 100644 -index 0000000000..fdcb324cd0 ---- /dev/null -+++ b/gnovm/stdlibs/frame_test.go -@@ -0,0 +1,125 @@ -+package stdlibs -+ -+import ( -+ "testing" -+ -+ "github.com/stretchr/testify/assert" -+ -+ gno "github.com/gnolang/gno/gnovm/pkg/gnolang" -+) -+ -+func TestPrevRealmIsOrigin(t *testing.T) { -+ var ( -+ user = gno.DerivePkgAddr("user1.gno").Bech32() -+ ctx = ExecContext{ -+ OrigCaller: user, -+ } -+ ) -+ tests := []struct { -+ name string -+ machine *gno.Machine -+ expectedRealm Realm -+ expectedIsOriginCall bool -+ }{ -+ { -+ name: "no frames", -+ machine: &gno.Machine{ -+ Context: ctx, -+ Frames: []gno.Frame{}, -+ }, -+ expectedRealm: Realm{ -+ addr: user, -+ pkgPath: "", -+ }, -+ expectedIsOriginCall: true, -+ }, -+ { -+ name: "one frame w/o LastPackage", -+ machine: &gno.Machine{ -+ Context: ctx, -+ Frames: []gno.Frame{ -+ {LastPackage: nil}, -+ }, -+ }, -+ expectedRealm: Realm{ -+ addr: user, -+ pkgPath: "", -+ }, -+ expectedIsOriginCall: true, -+ }, -+ { -+ name: "one non-realm frame", -+ machine: &gno.Machine{ -+ Context: ctx, -+ Frames: []gno.Frame{ -+ {LastPackage: &gno.PackageValue{PkgPath: "gno.land/p/xxx"}}, -+ }, -+ }, -+ expectedRealm: Realm{ -+ addr: user, -+ pkgPath: "", -+ }, -+ expectedIsOriginCall: true, -+ }, -+ { -+ name: "one realm frame", -+ machine: &gno.Machine{ -+ Context: ctx, -+ Frames: []gno.Frame{ -+ {LastPackage: &gno.PackageValue{PkgPath: "gno.land/r/xxx"}}, -+ }, -+ }, -+ expectedRealm: Realm{ -+ addr: user, -+ pkgPath: "", -+ }, -+ expectedIsOriginCall: true, -+ }, -+ { -+ name: "multiple frames with one realm", -+ machine: &gno.Machine{ -+ Context: ctx, -+ Frames: []gno.Frame{ -+ {LastPackage: &gno.PackageValue{PkgPath: "gno.land/p/xxx"}}, -+ {LastPackage: &gno.PackageValue{PkgPath: "gno.land/p/xxx"}}, -+ {LastPackage: &gno.PackageValue{PkgPath: "gno.land/r/xxx"}}, -+ }, -+ }, -+ expectedRealm: Realm{ -+ addr: user, -+ pkgPath: "", -+ }, -+ expectedIsOriginCall: true, -+ }, -+ { -+ name: "multiple frames with multiple realms", -+ machine: &gno.Machine{ -+ Context: ctx, -+ Frames: []gno.Frame{ -+ {LastPackage: &gno.PackageValue{PkgPath: "gno.land/r/zzz"}}, -+ {LastPackage: &gno.PackageValue{PkgPath: "gno.land/r/zzz"}}, -+ {LastPackage: &gno.PackageValue{PkgPath: "gno.land/r/yyy"}}, -+ {LastPackage: &gno.PackageValue{PkgPath: "gno.land/p/yyy"}}, -+ {LastPackage: &gno.PackageValue{PkgPath: "gno.land/p/xxx"}}, -+ {LastPackage: &gno.PackageValue{PkgPath: "gno.land/r/xxx"}}, -+ }, -+ }, -+ expectedRealm: Realm{ -+ addr: gno.DerivePkgAddr("gno.land/r/yyy").Bech32(), -+ pkgPath: "gno.land/r/yyy", -+ }, -+ expectedIsOriginCall: false, -+ }, -+ } -+ for _, tt := range tests { -+ t.Run(tt.name, func(t *testing.T) { -+ assert := assert.New(t) -+ -+ realm := prevRealm(tt.machine) -+ isOrigin := isOriginCall(tt.machine) -+ -+ assert.Equal(tt.expectedRealm, realm) -+ assert.Equal(tt.expectedIsOriginCall, isOrigin) -+ }) -+ } -+} -diff --git a/gnovm/stdlibs/stdlibs.go b/gnovm/stdlibs/stdlibs.go -index fb230a0cf8..2e73665a18 100644 ---- a/gnovm/stdlibs/stdlibs.go -+++ b/gnovm/stdlibs/stdlibs.go -@@ -151,8 +151,7 @@ func InjectPackage(store gno.Store, pn *gno.PackageNode) { - gno.Flds( // results - ), - func(m *gno.Machine) { -- isOrigin := len(m.Frames) == 2 -- if !isOrigin { -+ if !isOriginCall(m) { - m.Panic(typedString("invalid non-origin call")) - return - } -@@ -165,7 +164,7 @@ func InjectPackage(store gno.Store, pn *gno.PackageNode) { - "isOrigin", "bool", - ), - func(m *gno.Machine) { -- isOrigin := len(m.Frames) == 2 -+ isOrigin := isOriginCall(m) - res0 := gno.TypedValue{T: gno.BoolType} - res0.SetBool(isOrigin) - m.PushValue(res0) -@@ -308,47 +307,13 @@ func InjectPackage(store gno.Store, pn *gno.PackageNode) { - "", "Realm", - ), - func(m *gno.Machine) { -- var ( -- ctx = m.Context.(ExecContext) -- // Default lastCaller is OrigCaller, the signer of the tx -- lastCaller = ctx.OrigCaller -- lastPkgPath = "" -- ) -- -- for i := m.NumFrames() - 1; i > 0; i-- { -- fr := m.Frames[i] -- if fr.LastPackage == nil || !fr.LastPackage.IsRealm() { -- // Ignore non-realm frame -- continue -- } -- pkgPath := fr.LastPackage.PkgPath -- // The first realm we encounter will be the one calling -- // this function; to get the calling realm determine the first frame -- // where fr.LastPackage changes. -- if lastPkgPath == "" { -- lastPkgPath = pkgPath -- } else if lastPkgPath == pkgPath { -- continue -- } else { -- lastCaller = fr.LastPackage.GetPkgAddr().Bech32() -- lastPkgPath = pkgPath -- break -- } -- } -- -- // Empty the pkgPath if we return a user -- if ctx.OrigCaller == lastCaller { -- lastPkgPath = "" -- } -+ realm := prevRealm(m) - - // Return the result - res0 := gno.Go2GnoValue( - m.Alloc, - m.Store, -- reflect.ValueOf(Realm{ -- addr: lastCaller, -- pkgPath: lastPkgPath, -- }), -+ reflect.ValueOf(realm), - ) - - realmT := store.GetType(gno.DeclaredTypeID("std", "Realm")) -diff --git a/gnovm/tests/files/std9.gno b/gnovm/tests/files/std9.gno -deleted file mode 100644 -index 95ccfb2c8a..0000000000 ---- a/gnovm/tests/files/std9.gno -+++ /dev/null -@@ -1,14 +0,0 @@ --package main -- --import "std" -- --func main() { -- defer func() { -- // assert panic is recoverable -- println(recover()) -- }() -- std.AssertOriginCall() --} -- --// Output: --// invalid non-origin call -diff --git a/gnovm/tests/files/zrealm_tests0.gno b/gnovm/tests/files/zrealm_tests0.gno -index cfb1f08c6f..036e91b8a8 100644 ---- a/gnovm/tests/files/zrealm_tests0.gno -+++ b/gnovm/tests/files/zrealm_tests0.gno -@@ -245,7 +245,7 @@ func main() { - // "BlockNode": null, - // "Location": { - // "File": "tests.gno", --// "Line": "42", -+// "Line": "50", - // "Nonce": "0", - // "PkgPath": "gno.land/r/demo/tests" - // } -@@ -301,7 +301,7 @@ func main() { - // "BlockNode": null, - // "Location": { - // "File": "tests.gno", --// "Line": "42", -+// "Line": "50", - // "Nonce": "0", - // "PkgPath": "gno.land/r/demo/tests" - // } -@@ -734,6 +734,94 @@ func main() { - // { - // "T": { - // "@type": "/gno.FuncType", -+// "Params": [], -+// "Results": [] -+// }, -+// "V": { -+// "@type": "/gno.FuncValue", -+// "Closure": { -+// "@type": "/gno.RefValue", -+// "Escaped": true, -+// "ObjectID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:4" -+// }, -+// "FileName": "tests.gno", -+// "IsMethod": false, -+// "Name": "RSubtestsAssertOriginCall", -+// "PkgPath": "gno.land/r/demo/tests", -+// "Source": { -+// "@type": "/gno.RefNode", -+// "BlockNode": null, -+// "Location": { -+// "File": "tests.gno", -+// "Line": "31", -+// "Nonce": "0", -+// "PkgPath": "gno.land/r/demo/tests" -+// } -+// }, -+// "Type": { -+// "@type": "/gno.FuncType", -+// "Params": [], -+// "Results": [] -+// } -+// } -+// }, -+// { -+// "T": { -+// "@type": "/gno.FuncType", -+// "Params": [], -+// "Results": [ -+// { -+// "Embedded": false, -+// "Name": "", -+// "Tag": "", -+// "Type": { -+// "@type": "/gno.PrimitiveType", -+// "value": "4" -+// } -+// } -+// ] -+// }, -+// "V": { -+// "@type": "/gno.FuncValue", -+// "Closure": { -+// "@type": "/gno.RefValue", -+// "Escaped": true, -+// "ObjectID": "0ffe7732b4d549b4cf9ec18bd68641cd2c75ad0a:4" -+// }, -+// "FileName": "tests.gno", -+// "IsMethod": false, -+// "Name": "RSubtestsIsOriginCall", -+// "PkgPath": "gno.land/r/demo/tests", -+// "Source": { -+// "@type": "/gno.RefNode", -+// "BlockNode": null, -+// "Location": { -+// "File": "tests.gno", -+// "Line": "35", -+// "Nonce": "0", -+// "PkgPath": "gno.land/r/demo/tests" -+// } -+// }, -+// "Type": { -+// "@type": "/gno.FuncType", -+// "Params": [], -+// "Results": [ -+// { -+// "Embedded": false, -+// "Name": "", -+// "Tag": "", -+// "Type": { -+// "@type": "/gno.PrimitiveType", -+// "value": "4" -+// } -+// } -+// ] -+// } -+// } -+// }, -+// { -+// "T": { -+// "@type": "/gno.FuncType", - // "Params": [ - // { - // "Embedded": false, -@@ -766,7 +854,7 @@ func main() { - // "BlockNode": null, - // "Location": { - // "File": "tests.gno", --// "Line": "38", -+// "Line": "46", - // "Nonce": "0", - // "PkgPath": "gno.land/r/demo/tests" - // } -@@ -813,7 +901,7 @@ func main() { - // "BlockNode": null, - // "Location": { - // "File": "tests.gno", --// "Line": "60", -+// "Line": "68", - // "Nonce": "0", - // "PkgPath": "gno.land/r/demo/tests" - // } -@@ -847,7 +935,7 @@ func main() { - // "BlockNode": null, - // "Location": { - // "File": "tests.gno", --// "Line": "65", -+// "Line": "73", - // "Nonce": "0", - // "PkgPath": "gno.land/r/demo/tests" - // } -@@ -881,7 +969,7 @@ func main() { - // "BlockNode": null, - // "Location": { - // "File": "tests.gno", --// "Line": "73", -+// "Line": "81", - // "Nonce": "0", - // "PkgPath": "gno.land/r/demo/tests" - // } -@@ -925,7 +1013,7 @@ func main() { - // "BlockNode": null, - // "Location": { - // "File": "tests.gno", --// "Line": "77", -+// "Line": "85", - // "Nonce": "0", - // "PkgPath": "gno.land/r/demo/tests" - // } -@@ -979,7 +1067,7 @@ func main() { - // "BlockNode": null, - // "Location": { - // "File": "tests.gno", --// "Line": "81", -+// "Line": "89", - // "Nonce": "0", - // "PkgPath": "gno.land/r/demo/tests" - // } -@@ -1034,7 +1122,7 @@ func main() { - // "BlockNode": null, - // "Location": { - // "File": "tests.gno", --// "Line": "85", -+// "Line": "93", - // "Nonce": "0", - // "PkgPath": "gno.land/r/demo/tests" - // } -diff --git a/gnovm/tests/imports.go b/gnovm/tests/imports.go -index fc2820ce00..f4ad1a8d3e 100644 ---- a/gnovm/tests/imports.go -+++ b/gnovm/tests/imports.go -@@ -471,22 +471,6 @@ func TestStore(rootDir, filesPath string, stdin io.Reader, stdout, stderr io.Wri - func testPackageInjector(store gno.Store, pn *gno.PackageNode) { - // Also inject stdlibs native functions. - stdlibs.InjectPackage(store, pn) -- isOriginCall := func(m *gno.Machine) bool { -- tname := m.Frames[0].Func.Name -- switch tname { -- case "main": // test is a _filetest -- return len(m.Frames) == 3 -- case "runtest": // test is a _test -- return len(m.Frames) == 7 -- } -- // support init() in _filetest -- // XXX do we need to distinguish from 'runtest'/_test? -- // XXX pretty hacky even if not. -- if strings.HasPrefix(string(tname), "init.") { -- return len(m.Frames) == 3 -- } -- panic("unable to determine if test is a _test or a _filetest") -- } - // Test specific injections: - switch pn.PkgPath { - case "strconv": -@@ -497,34 +481,6 @@ func testPackageInjector(store gno.Store, pn *gno.PackageNode) { - case "std": - // NOTE: some of these are overrides. - // Also see stdlibs/InjectPackage. -- pn.DefineNativeOverride("AssertOriginCall", -- /* -- gno.Flds( // params -- ), -- gno.Flds( // results -- ), -- */ -- func(m *gno.Machine) { -- if !isOriginCall(m) { -- m.Panic(typedString("invalid non-origin call")) -- return -- } -- }, -- ) -- pn.DefineNativeOverride("IsOriginCall", -- /* -- gno.Flds( // params -- ), -- gno.Flds( // results -- "isOrigin", "bool", -- ), -- */ -- func(m *gno.Machine) { -- res0 := gno.TypedValue{T: gno.BoolType} -- res0.SetBool(isOriginCall(m)) -- m.PushValue(res0) -- }, -- ) - pn.DefineNativeOverride("GetCallerAt", - /* - gno.Flds( // params diff --git a/util/gnolanddev/run.sh b/util/gnolanddev/run.sh deleted file mode 100755 index f630ecca..00000000 --- a/util/gnolanddev/run.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash -set -eu - -rm -rf "$GNOROOT/gno.land" -mkdir -p "$GNOROOT" -cd "$GNOROOT" - -echo "copying stdlibs and examples from source..." -mkdir -p "$GNOROOT/gnovm" -rsync -a /opt/gno/src/gnovm/stdlibs "$GNOROOT/gnovm/" -rsync -a --delete /opt/gno/src/examples "$GNOROOT/" - -for gm in $(find /mnt -name 'gno.mod'); do - pkgpath="$(sed -n 's/^module \(.*\)$/\1/gp' "$gm")" - echo "adding module $pkgpath..." - mkdir -p "$GNOROOT/examples/$pkgpath" - # more conservative flags to avoid issues with entr. - rsync -a --delete --inplace "$(dirname "$gm")/" "$GNOROOT/examples/$pkgpath" -done - -mkdir -p gno.land/testdir/config gno.land/genesis -cp /opt/gno/src/gno.land/testdir/config/config.toml gno.land/testdir/config/ -rsync -ap /opt/gno/src/gno.land/genesis/ gno.land/genesis/ -echo "starting gnoland" -cd gno.land -gnoland start -genesis-max-vm-cycles 100''000''000 From 96189fcbd2a2d94ba8ccafb584559c4cee8f19ce Mon Sep 17 00:00:00 2001 From: Morgan Bazalgette Date: Fri, 9 Feb 2024 15:13:15 +0100 Subject: [PATCH 07/13] attempt to fix --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index fdfadb2e..67f37e50 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ GNOLAND ?= go run github.com/gnolang/gno/gno.land/cmd/gnoland GNOCMD ?= go run github.com/gnolang/gno/gnovm/cmd/gno GNODEV ?= go run github.com/gnolang/gno/contribs/gnodev -GNOROOT ?= `gno env GNOROOT` +GNOROOT ?= `$(GNOCMD) env GNOROOT` GNO_TEST_FLAGS ?= -verbose GNO_TEST_PKGS ?= gno.land/p/demo/chess/... gno.land/r/demo/chess From 1f8ae12bc6e5ab21e7dcad1553d8ab13ff39c90d Mon Sep 17 00:00:00 2001 From: Morgan Bazalgette Date: Fri, 9 Feb 2024 15:40:04 +0100 Subject: [PATCH 08/13] remove deploy realm ci, as it gets complicated now --- .github/workflows/deploy-realm.yml | 36 ------- .github/workflows/integration.yml | 2 +- .github/workflows/{realm.yml => test.yml} | 2 +- Makefile | 15 ++- integration_test.go | 99 ------------------- testdata/addpkg_gnochess.txtar | 5 - util/integration/integration_test.go | 12 +++ .../testdata/addpkg_gnochess.txtar | 5 + .../testdata}/gnochess-scholars-mate.txtar | 0 9 files changed, 30 insertions(+), 146 deletions(-) delete mode 100644 .github/workflows/deploy-realm.yml rename .github/workflows/{realm.yml => test.yml} (97%) delete mode 100644 integration_test.go delete mode 100644 testdata/addpkg_gnochess.txtar create mode 100644 util/integration/integration_test.go create mode 100644 util/integration/testdata/addpkg_gnochess.txtar rename {testdata => util/integration/testdata}/gnochess-scholars-mate.txtar (100%) diff --git a/.github/workflows/deploy-realm.yml b/.github/workflows/deploy-realm.yml deleted file mode 100644 index a68c0ad0..00000000 --- a/.github/workflows/deploy-realm.yml +++ /dev/null @@ -1,36 +0,0 @@ -name: realm - -on: - push: - paths: - - "realm/**" - branches: - - main - -env: - GNOKEY: "go run github.com/gnolang/gno/gno.land/cmd/gnokey" - GNOCHESS_REALM: gno.land/r/demo/chess_${GITHUB_SHA} - GNOLAND_REMOTE_CHAIN: "https://rpc.gnochess.com:443" - 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" - -jobs: - deploy-realm: - runs-on: ubuntu-latest - timeout-minutes: 10 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-go@v4 - with: - go-version: "stable" - - run: go mod download -x - - run: | - printf '\n\n%s\n\n' "$MNEMONIC" | $GNOKEY add --recover --insecure-password-stdin test1' - cd realm - echo "" | $GNOKEY maketx addpkg \ - --gas-wanted 50000000 \ - --gas-fee 1ugnot \ - --pkgpath gno.land/r/demo/chess_${GITHUB_SHA} \ - --pkgdir . \ - --insecure-password-stdin \ - --remote \ - --broadcast test1' diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 382e97ce..190ba59f 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -19,4 +19,4 @@ jobs: - uses: actions/setup-go@v4 with: go-version: 'stable' - - run: go test -v -run='TestIntegration/.*' . + - run: make test.integration diff --git a/.github/workflows/realm.yml b/.github/workflows/test.yml similarity index 97% rename from .github/workflows/realm.yml rename to .github/workflows/test.yml index f89c98b0..2b24e278 100644 --- a/.github/workflows/realm.yml +++ b/.github/workflows/test.yml @@ -1,4 +1,4 @@ -name: realm +name: test on: pull_request: diff --git a/Makefile b/Makefile index 67f37e50..c9fe3e8d 100644 --- a/Makefile +++ b/Makefile @@ -37,13 +37,21 @@ test.prepare: cp -r "$(PWD)/realm" ".test/examples/gno.land/r/demo/chess" .PHONY: test -test: test.prepare ## Test packages and realms. +test: test.prepare ## Test packages and realms using gno, excluding perft tests. cd .test/examples; GNOROOT="$(PWD)/.test" $(GNOCMD) test -run '^Test(?:[^P]|P[^e]|Pe[^r])' $(GNO_TEST_FLAGS) $(GNO_TEST_PKGS) .PHONY: test.perft test.perft: test.prepare ## Run perft tests. cd .test/examples; GNOROOT="$(PWD)/.test" $(GNOCMD) test -run 'TestPerft' $(GNO_TEST_FLAGS) gno.land/p/demo/chess +.PHONY: test.integration +test.integration: ## Test the realm using integration tests. + go test -v ./util/integration + +.PHONY: test.all +test.all: test test.perft test.integration ## Run all tests + +.PHONY: run.faucet run.faucet: ## Run the GnoChess faucet. cd faucet; go run main.go \ -fund-limit 250000000ugnot \ @@ -76,6 +84,7 @@ run.faucet: ## Run the GnoChess faucet. -mnemonic "$(MNEMONIC_TEST1)" \ -num-accounts 1 +.PHONY: run.web run.web: ## Run the web server. cd web; npm install ( \ @@ -88,6 +97,7 @@ run.web: ## Run the web server. cd web; npm run build cd web; npm run dev +.PHONY: run.gnodev run.gnodev: ## Run gnodev with the gnochess packages and realm. $(GNODEV) ./package/glicko2 ./package/zobrist ./package ./realm @@ -95,9 +105,6 @@ z_add_test1: ## Add the test1 key to gnokey. printf '\n\n%s\n\n' "$(MNEMONIC_TEST1)" | $(GNOKEY) add --recover --insecure-password-stdin test1 || true $(GNOKEY) list | grep test1 -z_test_integration: ## Test the realm using integration tests. - go test -v -run='TestIntegration/.*' . - z_build_realm: ## Precompile and build the generated Go files. Assumes a working clone of gno in ../gno. mkdir -p ../gno/examples/gno.land/r/gnochess cp -rf realm/*.gno ../gno/examples/gno.land/r/gnochess diff --git a/integration_test.go b/integration_test.go deleted file mode 100644 index f8f118a1..00000000 --- a/integration_test.go +++ /dev/null @@ -1,99 +0,0 @@ -package main - -import ( - "bufio" - "fmt" - "os" - "os/exec" - "path/filepath" - "testing" - "time" - - integration "github.com/gnolang/gno/gno.land/pkg/integration" - "github.com/jaekwon/testify/require" - "github.com/rogpeppe/go-internal/testscript" -) - -var balances = []string{ - "g1plqds6kxnfaqcpky0gtt6fpntfhjgcfx8r73a0=100000000000000000ugnot", - "g1sgy2zhqg2wecuz3qt8th63d539afagjnhs4zj3=100000000000000000ugnot", - "g1unk9a8yt595p4yxpfpejewvf9lx6yrvd2ylgtm=100000000000000000ugnot", - "g17x4qwuhmc6fyp6ut2qtscc9265xe5jnj83s8c6=100000000000000000ugnot", - "g1agq8t3289xxmm63z55axykmmve2pz87yqgyn5n=100000000000000000ugnot", - "g153xesqpfvr5y35l0aykew3796kz452zttp0xt2=100000000000000000ugnot", - "g18epncd7avkhmdlf930e4t2p7c7j9qdv3yda93f=100000000000000000ugnot", - "g1elguymy8sjjy246u09qddtx587934k6uzf8mc4=100000000000000000ugnot", - "g1sl70rzvu49mp0lstxaptmvle8h2a8rx8pu56uk=100000000000000000ugnot", - "g18dgugclk93v65qtxxus82eg30af59fgk246nqy=100000000000000000ugnot", - // test2 and test3, should be added from github.com/gnolang/gno/gno.land/pkg/integration - "g1m5exxkaqrsxd8ne93psljuakxzhkzcm42yg7ye=100000000000000000ugnot", - "g13hlh3a3kygwq9g3vgjzz5zu4fy7gpkk523ex6l=100000000000000000ugnot", -} - -func generateGenesisFile(genesispath, target string) error { - genesis, err := os.ReadFile(genesispath) - if err != nil { - return fmt.Errorf("Error reading genesis file: %w", err) - } - - outputFile, err := os.Create(target) - if err != nil { - return fmt.Errorf("Error creating output file: %w", err) - } - defer outputFile.Close() - - writer := bufio.NewWriter(outputFile) - writer.Write(genesis) - writer.WriteRune('\n') - writer.WriteRune('\n') - for _, line := range balances { - writer.WriteString(line) - writer.WriteRune('\n') - } - writer.Flush() - - return nil -} - -func TestIntegration(t *testing.T) { - ts := integration.SetupGnolandTestScript(t, "testdata") - - goModPath, err := exec.Command("go", "env", "GOMOD").CombinedOutput() - require.NoError(t, err) - - oldsetup := ts.Setup - idx := 0 - ts.Setup = func(e *testscript.Env) error { - oldsetup(e) - e.Setenv("ROOTDIR", filepath.Dir(string(goModPath))) - e.Setenv("NL", "\n") - - e.Setenv("GNOHOME", fmt.Sprintf("%s/%d", e.Getenv("GNOHOME"), idx)) - idx++ - - rootdir := e.Getenv("GNOROOT") - tmpdir := e.Getenv("TMPDIR") - - inputGenesis := filepath.Join(rootdir, "gno.land/genesis/genesis_balances.txt") - outputGenesis := filepath.Join(tmpdir, "genesis_balances.txt") - - if err := generateGenesisFile(inputGenesis, outputGenesis); err != nil { - return fmt.Errorf("unable to generate genesis file: %w", err) - } - return nil - } - - ts.Cmds["sleep"] = func(ts *testscript.TestScript, neg bool, args []string) { - d := time.Second - if len(args) > 0 { - var err error - if d, err = time.ParseDuration(args[0]); err != nil { - ts.Fatalf("uanble to parse duration %q: %s", args[1], err) - } - } - - time.Sleep(d) - } - - testscript.Run(t, ts) -} diff --git a/testdata/addpkg_gnochess.txtar b/testdata/addpkg_gnochess.txtar deleted file mode 100644 index 35652d18..00000000 --- a/testdata/addpkg_gnochess.txtar +++ /dev/null @@ -1,5 +0,0 @@ -gnoland start -genesis-balances-file=${TMPDIR}/genesis_balances.txt -genesis-max-vm-cycles 100000000 - -sleep 500ms - -gnokey maketx addpkg -pkgdir ${ROOTDIR}/realm -pkgpath gno.land/r/demo/chess2 -gas-wanted 20000000 -gas-fee 1ugnot -chainid=tendermint_test -broadcast test1 diff --git a/util/integration/integration_test.go b/util/integration/integration_test.go new file mode 100644 index 00000000..48907fba --- /dev/null +++ b/util/integration/integration_test.go @@ -0,0 +1,12 @@ +package integ + +import ( + "testing" + + integration "github.com/gnolang/gno/gno.land/pkg/integration" +) + +func TestIntegration(t *testing.T) { + t.Skip("Integration tests are currently disabled: https://github.com/gnolang/gnochess/issues/209") + integration.RunGnolandTestscripts(t, "testdata") +} diff --git a/util/integration/testdata/addpkg_gnochess.txtar b/util/integration/testdata/addpkg_gnochess.txtar new file mode 100644 index 00000000..41396ddb --- /dev/null +++ b/util/integration/testdata/addpkg_gnochess.txtar @@ -0,0 +1,5 @@ +gnoland start + +exec ls + +gnokey maketx addpkg -pkgdir $WORK/registry -pkgpath gno.land/r/registry -gas-fee 1000000ugnot -gas-wanted 2000000 -broadcast -chainid=tendermint_test test1 diff --git a/testdata/gnochess-scholars-mate.txtar b/util/integration/testdata/gnochess-scholars-mate.txtar similarity index 100% rename from testdata/gnochess-scholars-mate.txtar rename to util/integration/testdata/gnochess-scholars-mate.txtar From a66eca33d32cc0e0499a0e5000dc0e19f17b1089 Mon Sep 17 00:00:00 2001 From: Morgan Bazalgette Date: Fri, 9 Feb 2024 16:03:47 +0100 Subject: [PATCH 09/13] place all marshalers together --- Makefile | 1 + faucet/main.go | 2 +- package/glicko2/glicko2.gno | 30 ------------------------------ realm/discovery.gno | 33 ++++++++++++++++++++++++++++++++- 4 files changed, 34 insertions(+), 32 deletions(-) diff --git a/Makefile b/Makefile index c9fe3e8d..29043f72 100644 --- a/Makefile +++ b/Makefile @@ -57,6 +57,7 @@ run.faucet: ## Run the GnoChess faucet. -fund-limit 250000000ugnot \ -send-amount 1000000000ugnot \ -chain-id tendermint_test \ + -remote http://127.0.0.1:36657 \ -tokens juhb8a7p1D -tokens 6wrBVqzBgQ -tokens Ko3z72NaQm -tokens 6j7v0lDR39 -tokens xqh4stG702 \ -tokens lWGjlfP5rs -tokens UG8f8igNO6 -tokens b3JUurpCFb -tokens 4azfjy6hE9 -tokens dzNR5KAz2r \ -tokens lZOO7O5OeE -tokens epxa67WQ2c -tokens GnfMj2sDCO -tokens kDN7hiiSWE -tokens OtLfdJC279 \ diff --git a/faucet/main.go b/faucet/main.go index 36333009..7df63d51 100644 --- a/faucet/main.go +++ b/faucet/main.go @@ -37,7 +37,7 @@ const ( defaultGasFee = "1000000ugnot" defaultGasWanted = "100000" defaultFundLimit = "100ugnot" - defaultRemote = "http://127.0.0.1:36657" + defaultRemote = "http://127.0.0.1:26657" ) const ( diff --git a/package/glicko2/glicko2.gno b/package/glicko2/glicko2.gno index 45ab44c8..46fc6d7b 100644 --- a/package/glicko2/glicko2.gno +++ b/package/glicko2/glicko2.gno @@ -50,36 +50,6 @@ func NewPlayerRating(addr std.Address) *PlayerRating { } } -func (p PlayerRating) MarshalJSON() ([]byte, error) { - var buf bytes.Buffer - buf.WriteByte('{') - buf.WriteString(`"rating":` + formatFloat(p.Rating, 5) + `,`) - buf.WriteString(`"deviation":` + formatFloat(p.RatingDeviation, 5) + `,`) - buf.WriteString(`"volatility":` + formatFloat(p.RatingVolatility, 5)) - buf.WriteByte('}') - return buf.Bytes(), nil -} - -// XXX: dumb formatFloat implementation while we don't have strconv.FormatFloat -// https://github.com/gnolang/gno/pull/1464 -func formatFloat(f float64, decimals int) string { - if decimals > 10 { - decimals = 10 - } - neg := "" - if f < 0 { - f *= -1 - neg = "-" - } - const zeroes = "0000000000" // 10 zeroes - whole := math.Floor(f) - fractional := f - whole - leading := strconv.Itoa(int(whole)) - trailing := strconv.Itoa(int(fractional * 1e10)) - trailing = zeroes[:10-len(trailing)] + trailing - return neg + leading + "." + trailing -} - // RatingScore is the outcome of a game between two players. type RatingScore struct { White, Black std.Address diff --git a/realm/discovery.gno b/realm/discovery.gno index db8b58f7..ba20744b 100644 --- a/realm/discovery.gno +++ b/realm/discovery.gno @@ -5,6 +5,7 @@ package chess import ( "bytes" + "math" "sort" "std" "strconv" @@ -113,6 +114,36 @@ func (p Player) LeaderboardPosition(cat Category) int { return pos } +func marshalPlayerRating(p *glicko2.PlayerRating) ([]byte, error) { + var buf bytes.Buffer + buf.WriteByte('{') + buf.WriteString(`"rating":` + formatFloat(p.Rating, 5) + `,`) + buf.WriteString(`"deviation":` + formatFloat(p.RatingDeviation, 5) + `,`) + buf.WriteString(`"volatility":` + formatFloat(p.RatingVolatility, 5)) + buf.WriteByte('}') + return buf.Bytes(), nil +} + +// XXX: dumb formatFloat implementation while we don't have strconv.FormatFloat +// https://github.com/gnolang/gno/pull/1464 +func formatFloat(f float64, decimals int) string { + if decimals > 10 { + decimals = 10 + } + neg := "" + if f < 0 { + f *= -1 + neg = "-" + } + const zeroes = "0000000000" // 10 zeroes + whole := math.Floor(f) + fractional := f - whole + leading := strconv.Itoa(int(whole)) + trailing := strconv.Itoa(int(fractional * 1e10)) + trailing = zeroes[:10-len(trailing)] + trailing + return neg + leading + "." + trailing +} + func (p Player) MarshalJSON() ([]byte, error) { u := users.GetUserByAddress(p.Address) @@ -133,7 +164,7 @@ func (p Player) MarshalJSON() ([]byte, error) { buf.WriteString(`"losses":` + strconv.Itoa(stat.Losses) + ",") buf.WriteString(`"draws":` + strconv.Itoa(stat.Draws) + ",") buf.WriteString(`"rating":`) - if res, err := stat.PlayerRating.MarshalJSON(); err != nil { + if res, err := marshalPlayerRating(stat.PlayerRating); err != nil { return nil, err } else { buf.Write(res) From f127e974550532661d76fcc53370448f7b73d35a Mon Sep 17 00:00:00 2001 From: Morgan Bazalgette Date: Tue, 13 Feb 2024 20:52:20 +0100 Subject: [PATCH 10/13] de-clutter, moving JSON marshalers to own file --- realm/chess.gno | 88 ------------------- realm/discovery.gno | 68 --------------- realm/json.gno | 204 ++++++++++++++++++++++++++++++++++++++++++++ realm/time.gno | 27 ------ 4 files changed, 204 insertions(+), 183 deletions(-) create mode 100644 realm/json.gno diff --git a/realm/chess.gno b/realm/chess.gno index 4961a18e..01d39d7c 100644 --- a/realm/chess.gno +++ b/realm/chess.gno @@ -47,80 +47,6 @@ func (g Game) json() string { return string(s) } -func (g Game) MarshalJSON() (_ []byte, err error) { - var b bytes.Buffer - b.WriteByte('{') - - nilAddr := func(na *std.Address) string { - if na == nil { - return `null` - } - return `"` + na.String() + `"` - } - mjson := func(s string, val func() ([]byte, error), comma bool) { - if err != nil { - return - } - var res []byte - res, err = val() - if err != nil { - return - } - b.WriteString(`"` + s + `":`) - b.Write(res) - if comma { - b.WriteByte(',') - } - } - - b.WriteString(`"id":"` + g.ID + `",`) - b.WriteString(`"white":"` + g.White.String() + `",`) - b.WriteString(`"black":"` + g.Black.String() + `",`) - - mjson("position", marshalPosition(g.Position), true) - mjson("state", g.State.MarshalJSON, true) - mjson("winner", g.Winner.MarshalJSON, true) - if err != nil { - return - } - - b.WriteString(`"creator":"` + g.Creator.String() + `",`) - b.WriteString(`"created_at":"` + g.CreatedAt.Format(time.RFC3339) + `",`) - b.WriteString(`"draw_offerer":` + nilAddr(g.DrawOfferer) + ",") - b.WriteString(`"concluder":` + nilAddr(g.Concluder) + ",") - - mjson("time", g.Time.MarshalJSON, false) - if err != nil { - return - } - - b.WriteByte('}') - return b.Bytes(), nil -} - -func marshalPosition(p chess.Position) func() ([]byte, error) { - return func() ([]byte, error) { - var b bytes.Buffer - b.WriteByte('{') - - bfen := p.EncodeFEN() - b.WriteString(`"fen":"` + bfen + `",`) - - b.WriteString(`"moves":[`) - - for idx, m := range p.Moves { - b.WriteString(`"` + m.String() + `"`) - if idx != len(p.Moves)-1 { - b.WriteByte(',') - } - } - - b.WriteByte(']') - b.WriteByte('}') - return b.Bytes(), nil - } -} - // Winner represents the "direct" outcome of a game // (white, black or draw?) type Winner byte @@ -139,13 +65,6 @@ var winnerString = [...]string{ WinnerDraw: "draw", } -func (w Winner) MarshalJSON() ([]byte, error) { - if n := int(w); n < len(winnerString) { - return []byte(`"` + winnerString[n] + `"`), nil - } - return nil, errors.New("invalid winner value") -} - // GameState represents the current game state. type GameState byte @@ -191,13 +110,6 @@ var gameStatesSnake = [...]string{ GameStateDrawnByAgreement: "drawn_by_agreement", } -func (g GameState) MarshalJSON() ([]byte, error) { - if int(g) >= len(gameStatesSnake) { - return nil, errors.New("invalid game state") - } - return []byte(`"` + gameStatesSnake[g] + `"`), nil -} - // IsFinished returns whether the game is in a finished state. func (g GameState) IsFinished() bool { return g != GameStateOpen diff --git a/realm/discovery.gno b/realm/discovery.gno index ba20744b..f9178dd0 100644 --- a/realm/discovery.gno +++ b/realm/discovery.gno @@ -5,7 +5,6 @@ package chess import ( "bytes" - "math" "sort" "std" "strconv" @@ -114,73 +113,6 @@ func (p Player) LeaderboardPosition(cat Category) int { return pos } -func marshalPlayerRating(p *glicko2.PlayerRating) ([]byte, error) { - var buf bytes.Buffer - buf.WriteByte('{') - buf.WriteString(`"rating":` + formatFloat(p.Rating, 5) + `,`) - buf.WriteString(`"deviation":` + formatFloat(p.RatingDeviation, 5) + `,`) - buf.WriteString(`"volatility":` + formatFloat(p.RatingVolatility, 5)) - buf.WriteByte('}') - return buf.Bytes(), nil -} - -// XXX: dumb formatFloat implementation while we don't have strconv.FormatFloat -// https://github.com/gnolang/gno/pull/1464 -func formatFloat(f float64, decimals int) string { - if decimals > 10 { - decimals = 10 - } - neg := "" - if f < 0 { - f *= -1 - neg = "-" - } - const zeroes = "0000000000" // 10 zeroes - whole := math.Floor(f) - fractional := f - whole - leading := strconv.Itoa(int(whole)) - trailing := strconv.Itoa(int(fractional * 1e10)) - trailing = zeroes[:10-len(trailing)] + trailing - return neg + leading + "." + trailing -} - -func (p Player) MarshalJSON() ([]byte, error) { - u := users.GetUserByAddress(p.Address) - - var buf bytes.Buffer - buf.WriteByte('{') - - buf.WriteString(`"address":"` + p.Address.String() + `",`) - if u == nil { - buf.WriteString(`"username":"",`) - } else { - buf.WriteString(`"username":"` + u.Name() + `",`) - } - - for idx, cat := range categoryList { - stat := p.CategoryInfo[cat] - buf.WriteString(`"` + cat.String() + `":{`) - buf.WriteString(`"wins":` + strconv.Itoa(stat.Wins) + ",") - buf.WriteString(`"losses":` + strconv.Itoa(stat.Losses) + ",") - buf.WriteString(`"draws":` + strconv.Itoa(stat.Draws) + ",") - buf.WriteString(`"rating":`) - if res, err := marshalPlayerRating(stat.PlayerRating); err != nil { - return nil, err - } else { - buf.Write(res) - } - buf.WriteByte(',') - buf.WriteString(`"position":` + strconv.Itoa(p.LeaderboardPosition(cat))) - buf.WriteByte('}') - if idx != len(categoryList)-1 { - buf.WriteByte(',') - } - } - - buf.WriteByte('}') - return buf.Bytes(), nil -} - func (g *Game) saveResult() { w, b := getPlayer(g.White), getPlayer(g.Black) diff --git a/realm/json.gno b/realm/json.gno new file mode 100644 index 00000000..7daf3eda --- /dev/null +++ b/realm/json.gno @@ -0,0 +1,204 @@ +package chess + +import ( + "bytes" + "errors" + "math" + "std" + "strconv" + "time" + + "gno.land/p/demo/chess" + "gno.land/p/demo/chess/glicko2" + "gno.land/r/demo/users" +) + +// This file contains a bunch of JSON marshalers. +// These should disappear eventually! +// https://github.com/gnolang/gno/issues/1655 + +func (g Game) MarshalJSON() (_ []byte, err error) { + var b bytes.Buffer + b.WriteByte('{') + + nilAddr := func(na *std.Address) string { + if na == nil { + return `null` + } + return `"` + na.String() + `"` + } + mjson := func(s string, val interface{ MarshalJSON() ([]byte, error) }, comma bool) { + if err != nil { + return + } + var res []byte + res, err = val.MarshalJSON() + if err != nil { + return + } + b.WriteString(`"` + s + `":`) + b.Write(res) + if comma { + b.WriteByte(',') + } + } + + b.WriteString(`"id":"` + g.ID + `",`) + b.WriteString(`"white":"` + g.White.String() + `",`) + b.WriteString(`"black":"` + g.Black.String() + `",`) + + mjson("position", jsonPosition{g.Position}, true) + mjson("state", g.State, true) + mjson("winner", g.Winner, true) + if err != nil { + return + } + + b.WriteString(`"creator":"` + g.Creator.String() + `",`) + b.WriteString(`"created_at":"` + g.CreatedAt.Format(time.RFC3339) + `",`) + b.WriteString(`"draw_offerer":` + nilAddr(g.DrawOfferer) + ",") + b.WriteString(`"concluder":` + nilAddr(g.Concluder) + ",") + + mjson("time", g.Time, false) + if err != nil { + return + } + + b.WriteByte('}') + return b.Bytes(), nil +} + +type jsonPosition struct { + chess.Position +} + +func (p jsonPosition) MarshalJSON() ([]byte, error) { + var b bytes.Buffer + b.WriteByte('{') + + bfen := p.EncodeFEN() + b.WriteString(`"fen":"` + bfen + `",`) + + b.WriteString(`"moves":[`) + + for idx, m := range p.Moves { + b.WriteString(`"` + m.String() + `"`) + if idx != len(p.Moves)-1 { + b.WriteByte(',') + } + } + + b.WriteByte(']') + b.WriteByte('}') + return b.Bytes(), nil +} + +func (w Winner) MarshalJSON() ([]byte, error) { + if n := int(w); n < len(winnerString) { + return []byte(`"` + winnerString[n] + `"`), nil + } + return nil, errors.New("invalid winner value") +} + +func (g GameState) MarshalJSON() ([]byte, error) { + if int(g) >= len(gameStatesSnake) { + return nil, errors.New("invalid game state") + } + return []byte(`"` + gameStatesSnake[g] + `"`), nil +} + +func (tc *TimeControl) MarshalJSON() ([]byte, error) { + if tc == nil { + return []byte("null"), nil + } + var buf bytes.Buffer + + buf.WriteByte('{') + buf.WriteString(`"seconds":` + strconv.Itoa(tc.Seconds) + `,`) + buf.WriteString(`"increment":` + strconv.Itoa(tc.Increment) + `,`) + buf.WriteString(`"started_at":"` + tc.StartedAt.Format(time.RFC3339) + `",`) + + buf.WriteString(`"move_timestamps":[`) + for idx, mt := range tc.MoveTimestamps { + buf.WriteString(`"` + mt.Format(time.RFC3339) + `"`) + if idx != len(tc.MoveTimestamps)-1 { + buf.WriteByte(',') + } + } + buf.WriteString("],") + + buf.WriteString(`"white_time":` + strconv.FormatInt(tc.WhiteTime.Milliseconds(), 10) + ",") + buf.WriteString(`"black_time":` + strconv.FormatInt(tc.BlackTime.Milliseconds(), 10)) + buf.WriteByte('}') + + return buf.Bytes(), nil +} + +func (p Player) MarshalJSON() ([]byte, error) { + u := users.GetUserByAddress(p.Address) + + var buf bytes.Buffer + buf.WriteByte('{') + + buf.WriteString(`"address":"` + p.Address.String() + `",`) + if u == nil { + buf.WriteString(`"username":"",`) + } else { + buf.WriteString(`"username":"` + u.Name() + `",`) + } + + for idx, cat := range categoryList { + stat := p.CategoryInfo[cat] + buf.WriteString(`"` + cat.String() + `":{`) + buf.WriteString(`"wins":` + strconv.Itoa(stat.Wins) + ",") + buf.WriteString(`"losses":` + strconv.Itoa(stat.Losses) + ",") + buf.WriteString(`"draws":` + strconv.Itoa(stat.Draws) + ",") + buf.WriteString(`"rating":`) + if res, err := (jsonPlayerRating{stat.PlayerRating}).MarshalJSON(); err != nil { + return nil, err + } else { + buf.Write(res) + } + buf.WriteByte(',') + buf.WriteString(`"position":` + strconv.Itoa(p.LeaderboardPosition(cat))) + buf.WriteByte('}') + if idx != len(categoryList)-1 { + buf.WriteByte(',') + } + } + + buf.WriteByte('}') + return buf.Bytes(), nil +} + +type jsonPlayerRating struct{ *glicko2.PlayerRating } + +func (p jsonPlayerRating) MarshalJSON() ([]byte, error) { + var buf bytes.Buffer + buf.WriteByte('{') + buf.WriteString(`"rating":` + formatFloat(p.Rating, 5) + `,`) + buf.WriteString(`"deviation":` + formatFloat(p.RatingDeviation, 5) + `,`) + buf.WriteString(`"volatility":` + formatFloat(p.RatingVolatility, 5)) + buf.WriteByte('}') + return buf.Bytes(), nil +} + +// XXX: dumb formatFloat implementation while we don't have strconv.FormatFloat +// https://github.com/gnolang/gno/pull/1464 +func formatFloat(f float64, decimals int) string { + if decimals > 10 { + decimals = 10 + } + neg := "" + if f < 0 { + f *= -1 + neg = "-" + } + const zeroes = "0000000000" // 10 zeroes + whole := math.Floor(f) + fractional := f - whole + leading := strconv.Itoa(int(whole)) + trailing := strconv.Itoa(int(fractional * 1e10)) + trailing = zeroes[:10-len(trailing)] + trailing + return neg + leading + "." + trailing +} diff --git a/realm/time.gno b/realm/time.gno index 302a5d92..637e5b4c 100644 --- a/realm/time.gno +++ b/realm/time.gno @@ -31,33 +31,6 @@ func NewTimeControl(seconds, incr int) *TimeControl { } } -func (tc *TimeControl) MarshalJSON() ([]byte, error) { - if tc == nil { - return []byte("null"), nil - } - var buf bytes.Buffer - - buf.WriteByte('{') - buf.WriteString(`"seconds":` + strconv.Itoa(tc.Seconds) + `,`) - buf.WriteString(`"increment":` + strconv.Itoa(tc.Increment) + `,`) - buf.WriteString(`"started_at":"` + tc.StartedAt.Format(time.RFC3339) + `",`) - - buf.WriteString(`"move_timestamps":[`) - for idx, mt := range tc.MoveTimestamps { - buf.WriteString(`"` + mt.Format(time.RFC3339) + `"`) - if idx != len(tc.MoveTimestamps)-1 { - buf.WriteByte(',') - } - } - buf.WriteString("],") - - buf.WriteString(`"white_time":` + strconv.FormatInt(tc.WhiteTime.Milliseconds(), 10) + ",") - buf.WriteString(`"black_time":` + strconv.FormatInt(tc.BlackTime.Milliseconds(), 10)) - buf.WriteByte('}') - - return buf.Bytes(), nil -} - // AddMove records that at the current time, a new move was added. func (tc *TimeControl) AddMove() (valid bool) { nd, v := tc.timedOut() From 1ebccbf74203948b9c0a29820ca93da1048cd0a6 Mon Sep 17 00:00:00 2001 From: Morgan Bazalgette Date: Wed, 14 Feb 2024 16:13:28 +0100 Subject: [PATCH 11/13] docker's not working, I'll just leave it here for now --- .dockerignore | 1 + .github/workflows/test.yml | 2 +- Dockerfile | 5 + docker-compose.yml | 53 +++++++-- util/node-config.toml | 238 +++++++++++++++++++++++++++++++++++++ 5 files changed, 289 insertions(+), 10 deletions(-) create mode 100644 Dockerfile create mode 100644 util/node-config.toml diff --git a/.dockerignore b/.dockerignore index e99d0488..9fcf3305 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,2 +1,3 @@ .tmp .git +*.gen.go diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2b24e278..fa6a548b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,7 +4,7 @@ on: pull_request: paths: - "realm/**" - - "packages/**" + - "package/**" - "Makefile" - "go.sum" push: diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..a370dd54 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,5 @@ +FROM ghcr.io/gnolang/gno:latest + +COPY ./util/node-config.toml ./gno.land/testdir/config/config.toml +COPY ./package ./examples/gno.land/p/demo/chess +COPY ./realm ./examples/gno.land/r/demo/chess diff --git a/docker-compose.yml b/docker-compose.yml index 797e5748..3b50c442 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,18 +4,25 @@ volumes: gnonode: {} faucet: {} +networks: + gnochess: + enable_ipv6: false + services: gnoland: - build: ./util/gnolanddev + build: . + image: ghcr.io/gnolang/gnochess:latest environment: - LOG_LEVEL=4 - volumes: - - "gnonode:/opt/gno/src/testdir" - - "./util/gnolanddev/config.toml:/opt/gno/src/gno.land/testdir/config/config.toml" - - ".:/mnt" ports: - - 26657:26657 + - "26657:26657" restart: on-failure + working_dir: /opt/gno/src/gno.land + command: gnoland start + sysctls: + - net.ipv6.conf.all.disable_ipv6=1 + networks: + gnochess: logging: driver: "json-file" options: @@ -23,12 +30,17 @@ services: max-size: "100m" gnoweb: - image: ghcr.io/gnolang/gno:latest + build: . + image: ghcr.io/gnolang/gnochess:latest working_dir: /opt/gno/src/gno.land command: gnoweb -bind 0.0.0.0:8888 -remote gnoland:26657 + sysctls: + - net.ipv6.conf.all.disable_ipv6=1 ports: - - 8888:8888 + - "8888:8888" restart: on-failure + networks: + gnochess: logging: driver: "json-file" options: @@ -37,9 +49,14 @@ services: web: build: ./web + image: ghcr.io/gnolang/gnochess/web:latest + sysctls: + - net.ipv6.conf.all.disable_ipv6=1 ports: - - 1313:1313 + - "1313:1313" restart: on-failure + networks: + gnochess: logging: driver: "json-file" options: @@ -55,6 +72,10 @@ services: redis: image: "redis:7.2" + networks: + gnochess: + sysctls: + - net.ipv6.conf.all.disable_ipv6=1 ports: - "6379:6379" @@ -63,6 +84,8 @@ services: depends_on: - "redis" - "gnoland" + sysctls: + - net.ipv6.conf.all.disable_ipv6=1 command: - "go" - "run" @@ -79,11 +102,17 @@ services: volumes: - "faucet:/go" - "./faucet:/app" + ports: + - "5050:5050" + networks: + gnochess: signup-web: image: node command: ["yarn", "run", "dev", "--host=0.0.0.0", "--port=8080"] working_dir: "/app" + sysctls: + - net.ipv6.conf.all.disable_ipv6=1 volumes: - "./signup:/app" ports: @@ -91,10 +120,14 @@ services: environment: VITE_API_BASE_URL: "localhost:8080" VITE_NETLIFY_FUNCTIONS_URL: "http://localhost:9000" + networks: + gnochess: signup-functions: image: williamjackson/netlify-cli stop_grace_period: 500ms # XXX: improve by making this a dockerfile which has dumb-init + sysctls: + - net.ipv6.conf.all.disable_ipv6=1 depends_on: - redis command: ["functions:serve", "-f", "./functions", "-p", "9000"] @@ -106,3 +139,5 @@ services: environment: NODE_ENV: "development" REDIS_URL: "redis://redis:6379" + networks: + gnochess: diff --git a/util/node-config.toml b/util/node-config.toml new file mode 100644 index 00000000..c49ac4f4 --- /dev/null +++ b/util/node-config.toml @@ -0,0 +1,238 @@ +# This config is used in the Dockerfile to set up the default configuration. +# This is a TOML config file. +# For more information, see https://github.com/toml-lang/toml + +##### main base config options ##### + +# TCP or UNIX socket address of the ABCI application, +# or the name of an ABCI application compiled in with the Tendermint binary +proxy_app = "tcp://127.0.0.1:26658" + +# A custom human readable name for this node +moniker = "45-79-178-97" + +# If this node is many blocks behind the tip of the chain, FastSync +# allows them to catchup quickly by downloading blocks in parallel +# and verifying their commits +fast_sync = true + +# Database backend: goleveldb | cleveldb | boltdb +# * goleveldb (github.com/gnolang/goleveldb, fork of github.com/syndtr/goleveldb) - most popular implementation) +# - pure go +# - stable +# * cleveldb (uses levigo wrapper) +# - fast +# - requires gcc +# - use cleveldb build tag (go build -tags cleveldb) +# * boltdb (uses etcd's fork of bolt - go.etcd.io/bbolt) +# - EXPERIMENTAL +# - may be faster is some use-cases (random reads - indexer) +# - use boltdb build tag (go build -tags boltdb) +db_backend = "goleveldb" + +# Database directory +db_dir = "data" + +# Output level for logging, including package level options +log_level = "main:info,state:info,*:error" + +# Output format: 'plain' (colored text) or 'json' +log_format = "plain" + +##### additional base config options ##### + +# Path to the JSON file containing the initial validator set and other meta data +genesis_file = "config/genesis.json" + +# Path to the JSON file containing the private key to use as a validator in the consensus protocol +priv_validator_key_file = "config/priv_validator_key.json" + +# Path to the JSON file containing the last sign state of a validator +priv_validator_state_file = "data/priv_validator_state.json" + +# TCP or UNIX socket address for Tendermint to listen on for +# connections from an external PrivValidator process +priv_validator_laddr = "" + +# Path to the JSON file containing the private key to use for node authentication in the p2p protocol +node_key_file = "config/node_key.json" + +# Mechanism to connect to the ABCI application: socket | grpc +abci = "socket" + +# TCP or UNIX socket address for the profiling server to listen on +prof_laddr = "" + +# If true, query the ABCI app on connecting to a new peer +# so the app can decide if we should keep the connection or not +filter_peers = false + +##### advanced configuration options ##### + +##### rpc server configuration options ##### +[rpc] + +# TCP or UNIX socket address for the RPC server to listen on +laddr = "tcp://0.0.0.0:26657" + +# A list of origins a cross-domain request can be executed from +# Default value '[]' disables cors support +# Use '["*"]' to allow any origin +cors_allowed_origins = ["*"] + +# A list of methods the client is allowed to use with cross-domain requests +cors_allowed_methods = ["HEAD", "GET", "POST", ] + +# A list of non simple headers the client is allowed to use with cross-domain requests +cors_allowed_headers = ["Origin", "Accept", "Content-Type", "X-Requested-With", "X-Server-Time", ] + +# TCP or UNIX socket address for the gRPC server to listen on +# NOTE: This server only supports /broadcast_tx_commit +grpc_laddr = "" + +# Maximum number of simultaneous connections. +# Does not include RPC (HTTP&WebSocket) connections. See max_open_connections +# If you want to accept a larger number than the default, make sure +# you increase your OS limits. +# 0 - unlimited. +# Should be < {ulimit -Sn} - {MaxNumInboundPeers} - {MaxNumOutboundPeers} - {N of wal, db and other open files} +# 1024 - 40 - 10 - 50 = 924 = ~900 +grpc_max_open_connections = 900 + +# Activate unsafe RPC commands like /dial_seeds and /unsafe_flush_mempool +unsafe = false + +# Maximum number of simultaneous connections (including WebSocket). +# Does not include gRPC connections. See grpc_max_open_connections +# If you want to accept a larger number than the default, make sure +# you increase your OS limits. +# 0 - unlimited. +# Should be < {ulimit -Sn} - {MaxNumInboundPeers} - {MaxNumOutboundPeers} - {N of wal, db and other open files} +# 1024 - 40 - 10 - 50 = 924 = ~900 +max_open_connections = 900 + +# How long to wait for a tx to be committed during /broadcast_tx_commit. +# WARNING: Using a value larger than 10s will result in increasing the +# global HTTP write timeout, which applies to all connections and endpoints. +# See https://github.com/tendermint/classic/issues/3435 +timeout_broadcast_tx_commit = "10s" + +# Maximum size of request body, in bytes +max_body_bytes = 1000000 + +# Maximum size of request header, in bytes +max_header_bytes = 1048576 + +# The path to a file containing certificate that is used to create the HTTPS server. +# Might be either absolute path or path related to tendermint's config directory. +# If the certificate is signed by a certificate authority, +# the certFile should be the concatenation of the server's certificate, any intermediates, +# and the CA's certificate. +# NOTE: both tls_cert_file and tls_key_file must be present for Tendermint to create HTTPS server. Otherwise, HTTP server is run. +tls_cert_file = "" + +# The path to a file containing matching private key that is used to create the HTTPS server. +# Might be either absolute path or path related to tendermint's config directory. +# NOTE: both tls_cert_file and tls_key_file must be present for Tendermint to create HTTPS server. Otherwise, HTTP server is run. +tls_key_file = "" + +##### peer to peer configuration options ##### +[p2p] + +# Address to listen for incoming connections +laddr = "tcp://0.0.0.0:26656" + +# Address to advertise to peers for them to dial +# If empty, will use the same port as the laddr, +# and will introspect on the listener or use UPnP +# to figure out the address. +external_address = "" + +# Comma separated list of seed nodes to connect to +seeds = "" + +# Comma separated list of nodes to keep persistent connections to +persistent_peers = "" + +# UPNP port forwarding +upnp = false + +# Maximum number of inbound peers +max_num_inbound_peers = 40 + +# Maximum number of outbound peers to connect to, excluding persistent peers +max_num_outbound_peers = 10 + +# Time to wait before flushing messages out on the connection +flush_throttle_timeout = "100ms" + +# Maximum size of a message packet payload, in bytes +max_packet_msg_payload_size = 1024 + +# Rate at which packets can be sent, in bytes/second +send_rate = 5120000 + +# Rate at which packets can be received, in bytes/second +recv_rate = 5120000 + +# Set true to enable the peer-exchange reactor +pex = true + +# Seed mode, in which node constantly crawls the network and looks for +# peers. If another node asks it for addresses, it responds and disconnects. +# +# Does not work if the peer-exchange reactor is disabled. +seed_mode = false + +# Comma separated list of peer IDs to keep private (will not be gossiped to other peers) +private_peer_ids = "" + +# Toggle to disable guard against peers connecting from the same ip. +allow_duplicate_ip = false + +# Peer connection configuration. +handshake_timeout = "20s" +dial_timeout = "3s" + +##### mempool configuration options ##### +[mempool] + +recheck = true +broadcast = true +wal_dir = "" + +# Maximum number of transactions in the mempool +size = 5000 + +# Limit the total size of all txs in the mempool. +# This only accounts for raw transactions (e.g. given 1MB transactions and +# max_txs_bytes=5MB, mempool will only accept 5 transactions). +max_pending_txs_bytes = 1073741824 + +# Size of the cache (used to filter transactions we saw earlier) in transactions +cache_size = 10000 + +##### consensus configuration options ##### +[consensus] + +wal_file = "data/cs.wal/wal" + +timeout_propose = "3s" +timeout_propose_delta = "500ms" +timeout_prevote = "1s" +timeout_prevote_delta = "500ms" +timeout_precommit = "1s" +timeout_precommit_delta = "500ms" +timeout_commit = "5s" + +# Make progress as soon as we have all the precommits (as if TimeoutCommit = 0) +skip_timeout_commit = false + +# EmptyBlocks mode and possible interval between empty blocks +create_empty_blocks = true +create_empty_blocks_interval = "0s" + +# Reactor sleep duration parameters +peer_gossip_sleep_duration = "100ms" +peer_query_maj23_sleep_duration = "2s" + From 53788be06fbb3771d12519f5ee6393618d777fc1 Mon Sep 17 00:00:00 2001 From: Morgan Bazalgette Date: Wed, 14 Feb 2024 18:07:47 +0100 Subject: [PATCH 12/13] remove ipv6 stuff --- docker-compose.yml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 3b50c442..95f328f5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -19,8 +19,6 @@ services: restart: on-failure working_dir: /opt/gno/src/gno.land command: gnoland start - sysctls: - - net.ipv6.conf.all.disable_ipv6=1 networks: gnochess: logging: @@ -34,8 +32,6 @@ services: image: ghcr.io/gnolang/gnochess:latest working_dir: /opt/gno/src/gno.land command: gnoweb -bind 0.0.0.0:8888 -remote gnoland:26657 - sysctls: - - net.ipv6.conf.all.disable_ipv6=1 ports: - "8888:8888" restart: on-failure @@ -50,8 +46,6 @@ services: web: build: ./web image: ghcr.io/gnolang/gnochess/web:latest - sysctls: - - net.ipv6.conf.all.disable_ipv6=1 ports: - "1313:1313" restart: on-failure @@ -74,8 +68,6 @@ services: image: "redis:7.2" networks: gnochess: - sysctls: - - net.ipv6.conf.all.disable_ipv6=1 ports: - "6379:6379" @@ -84,8 +76,6 @@ services: depends_on: - "redis" - "gnoland" - sysctls: - - net.ipv6.conf.all.disable_ipv6=1 command: - "go" - "run" @@ -111,8 +101,6 @@ services: image: node command: ["yarn", "run", "dev", "--host=0.0.0.0", "--port=8080"] working_dir: "/app" - sysctls: - - net.ipv6.conf.all.disable_ipv6=1 volumes: - "./signup:/app" ports: @@ -126,8 +114,6 @@ services: signup-functions: image: williamjackson/netlify-cli stop_grace_period: 500ms # XXX: improve by making this a dockerfile which has dumb-init - sysctls: - - net.ipv6.conf.all.disable_ipv6=1 depends_on: - redis command: ["functions:serve", "-f", "./functions", "-p", "9000"] From 2359d6e1b8ac9a0073ac1ab99e65d79d824ab5a3 Mon Sep 17 00:00:00 2001 From: Morgan Bazalgette Date: Wed, 14 Feb 2024 18:58:02 +0100 Subject: [PATCH 13/13] update to readme --- README.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/README.md b/README.md index bc041858..13bc52de 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,39 @@ This repository hosts both the source code for the [GnoChess realm and website](https://gnochess.com), as well as a dedicted tutorial section, originally planned to accompany a talk for Gophercon 2023. +## Getting Started + +Running GnoChess has a few requirements: + +- Go 1.21+ +- Node 16+ +- make +- git +- A POSIX environment (ie. have a UNIX shell, so Linux or macOS. + WSL probably works but nobody tested it.) + +After cloning the repository, run `go get` to install the dependencies, then you +can get started by running the following: + +```sh +make run.web & make run.faucet & make run.gnodev +``` + +You can also call the three commands separately to have their individual +outputs; here is an example with tmux: + +![637248](https://github.com/gnolang/gnochess/assets/4681308/03433d02-85e3-40a5-bf3b-ba46efc5c65c) + +With that done, you will be able to access a (hopefully) working local set-up of +GnoChess on . At the time of writing, this still requires +access through a token: you can pick one of the ones available in the +[Makefile](Makefile) at the `run.faucet` section. (Annoying -- it will improve, +we're working on it!) + +There's a rudimentary set up for working with docker also available on our +[docker-compose file](docker-compose.yml), though for the time being the local +set up using make is recommended! + ## Workshop tutorial > A Workshop on Gnochess has been held at Gophercon San Diego on 26/09/2023.