-
Notifications
You must be signed in to change notification settings - Fork 379
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat!: forbid importing '/r' from '/p' #1393
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #1393 +/- ##
==========================================
- Coverage 48.38% 45.64% -2.75%
==========================================
Files 409 445 +36
Lines 62035 66249 +4214
==========================================
+ Hits 30018 30241 +223
- Misses 29517 33512 +3995
+ Partials 2500 2496 -4 ☔ View full report in Codecov by Sentry. |
Why would we want that ? Just for security issues ? I would suggest something else, since calling realm from package could be really useful ! For example, in the case of the merkle-airdrop contract i wrote. there is a package I already propose couple time ago to extends the |
gnovm/pkg/gnolang/nodes.go
Outdated
@@ -1146,6 +1146,7 @@ func PrecompileMemPackage(memPkg *std.MemPackage) error { | |||
} | |||
|
|||
// Returns the code fileset minus any spurious or test files. | |||
// Here? | |||
func ParseMemPackage(memPkg *std.MemPackage) (fset *FileSet) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe it's the ideal location for early arrivals, package uploads, and early cleanups. @piux2, could you please verify?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the Gno language environment, ParseMemPackage() in gnolang/nodes.go is called in six distinct scenarios, each with different contexts. These scenarios can be divided into three main categories: blockchain application, file testing, and local development.
Blockchain Application:
This involves the Gno language as an application running on the GnoLand blockchain. There are two specific scenarios under this category:
-
gno.land start
When this command is executed, the Gno virtual machine (VM) only reads the gnovm/stdlibs contracts from the local file system.
Instead of loading everything into memory, it initializes a package getter and loads packages during runtime as needed. -
gnokey maketx addpkg
In this case, the VM parses contracts loaded from the GnoLand app store on-chain.
All non-stdlib contracts (identified as "p" and "r") in the Gno app store are derived from the Tendermint Consensus and genesis transactions.
File Testing:
This scenario involves loading packages into a machine instance from a testing store, without involving blockchain applications. Packages can be loaded from the local file system.
go test ./tests -run '^TestFiles$'
import.TestStore() is used.
Gno Local Development and Test:
-
gno run
imports.TestStore() is used. -
gno repl
imports.TestStore() is used. -
gno test ./examples
Gno modules (Gno mod) are used to facilitate local development and testing. They are not entities on the blockchain.
The goal is to avoid mixing the logic of on-chain production, local development, and testing within the gnolang/nodes.go functions. Each scenario handles the parsing and loading of packages differently. therefore the logic should be implemted outside of the pure gnolang function in a language pkg for the specific needs.
graph TD
A[1 'gno.land start'] -->AB[makeGenesis] -->B[NewApp]
B --> C[VMKeeper.Initialize]
C --> D[m.PreprocessAllFilesAndSaveBlockNodes]
D --> E[gnolang/nodes.go: ParseMemPackage]
F[2 'gnokey maketx addpkg'] -->|Network| H[tm2.PRC]
H --> I[vmHandler]
I --> J[VMKeeper.AddPackage]
J --> U[m.RunMemPackage]
K[3 'go test ./tests -run '^TestFiles$''] --> L[RunFileTest]
L --> U
M[4 'gno run'] --> N[import.TestStore]
N --> U
O[5 'gno repl'] --> P[import.TestStore]
P --> U
Q['6 gno test ./examples'] --> R[execTest]
R -->S[gnoTestPkg]
S --> U
U --> E
style A stroke:#1548c6,stroke-width:2px
style F stroke:#1548c6,stroke-width:2px
style K stroke:#111111,stroke-width:2px
style M stroke:#111111,stroke-width:2px
style O stroke:#111111,stroke-width:2px
style Q stroke:#111111,stroke-width:2px
style E stroke:#b548c6,stroke-width:2px
style U stroke:#b548c6,stroke-width:2px
style D stroke:#b548c6,stroke-width:2px
Here's the list of pkgs importing realm:
Should I mark them as Draft until we figure out alternate way to call realm methods in pkgs? |
|
So, I've taken a look at this and tried to figure out where best this check could sit. Where current validation about import paths resides is in
It's always called internally within So, my proposed plan of action is the following:
|
The restriction really is on importing rather than calling. I think it makes a ton of sense to forbid importing from a package. A package is stateless, and importing a package and running its functions should not have side-effects unless clearly specified. Remember that the "realm" is considered an entity, which has its own coins in the banker and can send them to other realms. It can make calls to other realms which will identify the calls as coming from it through So it is important that "important" actions like calling other realms and using the banker are strictly authorised within the realm's source code. (The banker can currently be freely called by a package, I'm pretty sure, but I made a note that this should be fixed eventually). That said, if the realm does trust a package, it can very freely give the keys to its heart... package myrlm
import (
"std"
"strings"
"gno.land/p/demo/mypkg"
"gno.land/r/demo/boards"
pboards "gno.land/p/demo/boards"
)
func LendBanker() {
bnk := std.GetBanker(std.BankerTypeRealmSend)
// mypkg can now freely send coins from the realm's bank
mypkg.Lend(bnk)
}
func LendCall() {
// now mypkg can call boards.CreatePost because it was passed by a closure!
mypkg.LendCall(boards.CreatePost)
// but it can even decide not to "trust" mypkg...
mypkg.LendCall(func(x pboards.Post) {
if strings.Contains(strings.ToLower(x.Content), "ethereum") {
panic("bad package! >:(")
}
boards.CreatePost(x)
})
} This feature we're talking about is not about forbidding calls from packages; but rather making sure that what they do is not stateful unless explicitly authorised by the realm. It allows realm authors to know that while they always have to audit their dependencies, they can at least be sure their dependencies can never accidentally bankrupt them. |
Splits `r/demo/users` into `p/demo/users` and `r/demo/users` Related #1393 <details><summary>Contributors' checklist...</summary> - [x] Added new tests, or not needed, or not feasible - [x] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [x] Updated the official documentation or not needed - [x] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [x] Added references to related issues and PRs - [x] Provided any useful hints for running manual tests - [x] Added new benchmarks to [generated graphs](https://gnoland.github.io/benchmarks), if any. More info [here](https://github.com/gnolang/gno/blob/master/.benchmarks/README.md). </details>
Splits `r/demo/users` into `p/demo/users` and `r/demo/users` Related gnolang#1393 <details><summary>Contributors' checklist...</summary> - [x] Added new tests, or not needed, or not feasible - [x] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [x] Updated the official documentation or not needed - [x] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [x] Added references to related issues and PRs - [x] Provided any useful hints for running manual tests - [x] Added new benchmarks to [generated graphs](https://gnoland.github.io/benchmarks), if any. More info [here](https://github.com/gnolang/gno/blob/master/.benchmarks/README.md). </details>
b9682dc
to
42a14df
Compare
7d6907e
to
edfbdf9
Compare
edfbdf9
to
5ca873d
Compare
Let's find some time during the retreat to discuss this PR |
Closes #3040 50% of the work comes from @harry-hov's PR #1393 (let's repay to Caesar what belongs to Caesar) 🚀 Notable additions: - handle different domains (e.g github.com/p/demo/...) - skip non ``.gno`` files (LICENSE, README, ...) or empty files <details><summary>Contributors' checklist...</summary> - [x] Added new tests, or not needed, or not feasible - [x] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [x] Updated the official documentation or not needed - [x] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [x] Added references to related issues and PRs - [x] Provided any useful hints for running manual tests </details> --------- Co-authored-by: n0izn0iz <n0izn0iz@users.noreply.github.com> Co-authored-by: Morgan <git@howl.moe> Co-authored-by: Morgan <morgan@morganbaz.com>
Packages shouldn't be importing realms!
Depends on:
r/demo/users
#1433r/demo/boards
#1989