Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

render.gno

4.58 Kb · 106 lines
  1package provable
  2
  3import (
  4	"strconv"
  5	"strings"
  6)
  7
  8// Render serves the overview at "" and one entry with its proof at
  9// "entry/<index>".
 10//
 11// Output is a fixed size: the entry list is capped at renderEntries, so a full
 12// log still renders. The chain caps a query at maxGasQuery and a reader cannot
 13// raise it, so an unbounded Render is a permanently unreadable page.
 14func Render(path string) string {
 15	path = strings.TrimSpace(path)
 16	if strings.HasPrefix(path, "entry/") {
 17		return renderEntry(strings.TrimPrefix(path, "entry/"))
 18	}
 19	return renderIndex()
 20}
 21
 22func renderIndex() string {
 23	var b strings.Builder
 24	b.WriteString("# provable\n\n")
 25	b.WriteString("What gno.land can and cannot prove about itself, demonstrated rather than asserted.\n\n")
 26
 27	b.WriteString("## The log\n\n")
 28	b.WriteString("An append-only Merkle mountain range. Appending costs O(log n) hashes and never rebuilds.\n\n")
 29	b.WriteString("| Field | Value |\n|---|---|\n")
 30	b.WriteString("| Entries | " + strconv.Itoa(log.Size()) + " / " + strconv.Itoa(MaxEntries) + " |\n")
 31	b.WriteString("| Stored hashes | " + strconv.Itoa(log.Nodes()) + " |\n")
 32	b.WriteString("| Peaks | " + strconv.Itoa(len(log.PeakHashes())) + " |\n")
 33	b.WriteString("| Root | `" + rootOrDash() + "` |\n\n")
 34
 35	b.WriteString("This root is also the Tendermint simple-tree root over the same entries, so any\n")
 36	b.WriteString("Tendermint verifier accepts it. `Verify` and `VerifyFixed` check the two proof\n")
 37	b.WriteString("encodings against it.\n\n")
 38
 39	b.WriteString("## What the chain can prove\n\n")
 40	b.WriteString("`gno.land/pkg/gnoland/app.go` mounts exactly two stores. One is IAVL and merkleized,\n")
 41	b.WriteString("the other is a plain dbadapter whose `Commit` is documented as *\"Always returns a zero\n")
 42	b.WriteString("commitID, as dbadapter store doesn't merkleize\"*.\n\n")
 43	b.WriteString("| Data | Store | Provable against the app hash |\n|---|---|---|\n")
 44	b.WriteString("| Package source | iavl | yes |\n")
 45	b.WriteString("| Account balances | iavl | yes |\n")
 46	b.WriteString("| Escaped object hashes (cross-realm) | iavl | yes, the hash only |\n")
 47	b.WriteString("| Realm objects, types, realm metadata | base | **no** |\n")
 48	b.WriteString("| **This log** | base | **no** |\n\n")
 49
 50	b.WriteString("## What that means here\n\n")
 51	b.WriteString("A proof from this realm says *this entry is consistent with the root this realm\n")
 52	b.WriteString("published*. It cannot say *this root is the chain's own*, for two independent reasons:\n\n")
 53	b.WriteString("1. Realm state is not merkleized, so there is no state proof to produce.\n")
 54	b.WriteString("2. `chain/runtime` exposes `ChainID`, `ChainDomain`, `ChainHeight` and `GetSessionInfo`\n")
 55	b.WriteString("   and nothing else. No app hash, no block hash, no header. A realm has no trusted\n")
 56	b.WriteString("   root to check anything against.\n\n")
 57	b.WriteString("Anything built on Merkle proofs in a gno realm is trust-minimised relative to a\n")
 58	b.WriteString("committed root, never trustless. Saying otherwise would be the interesting-sounding\n")
 59	b.WriteString("half of a true story.\n\n")
 60
 61	b.WriteString("## Entries\n\n")
 62	if log.Size() == 0 {
 63		b.WriteString("_Empty. Call `Append(\"something\")`._\n")
 64		return b.String()
 65	}
 66	start := 0
 67	if len(entries) > renderEntries {
 68		start = len(entries) - renderEntries
 69		b.WriteString("Showing the last " + strconv.Itoa(renderEntries) + " of " + strconv.Itoa(len(entries)) + ".\n\n")
 70	}
 71	b.WriteString("| # | Entry |\n|---|---|\n")
 72	for i := start; i < len(entries); i++ {
 73		b.WriteString("| [" + strconv.Itoa(i) + "](/r/moul/x/provable/v0:entry/" + strconv.Itoa(i) + ") | " + entries[i] + " |\n")
 74	}
 75	return b.String()
 76}
 77
 78func renderEntry(raw string) string {
 79	i, err := strconv.Atoi(raw)
 80	if err != nil || i < 0 || i >= len(entries) {
 81		return "# provable\n\nNo entry `" + raw + "`.\n"
 82	}
 83	path, before, after := ProofOf(i)
 84	var b strings.Builder
 85	b.WriteString("# provable: entry " + strconv.Itoa(i) + "\n\n")
 86	b.WriteString("```\n" + entries[i] + "\n```\n\n")
 87	b.WriteString("## Inclusion proof\n\n")
 88	b.WriteString("| Field | Value |\n|---|---|\n")
 89	b.WriteString("| Index | " + strconv.Itoa(i) + " |\n")
 90	b.WriteString("| Total | " + strconv.Itoa(log.Size()) + " |\n")
 91	b.WriteString("| Path | `" + orDash(path) + "` |\n")
 92	b.WriteString("| Before | `" + orDash(before) + "` |\n")
 93	b.WriteString("| After | `" + orDash(after) + "` |\n")
 94	b.WriteString("| Root | `" + rootOrDash() + "` |\n\n")
 95	b.WriteString("Valid against that root only. The next `Append` moves it.\n")
 96	return b.String()
 97}
 98
 99func rootOrDash() string { return orDash(Root()) }
100
101func orDash(s string) string {
102	if s == "" {
103		return "-"
104	}
105	return s
106}