From 41d04a5facc85e8040cd472bb530df2821cb1df2 Mon Sep 17 00:00:00 2001 From: Manfred Touron <94029+moul@users.noreply.github.com> Date: Tue, 13 Sep 2022 13:31:09 +0000 Subject: [PATCH 1/3] chore: add std.ExecAsPkg Signed-off-by: Manfred Touron <94029+moul@users.noreply.github.com> --- stdlibs/stdlibs.go | 28 ++++++++++++++++++++++++++++ stdlibs/stdshim/stdshim.gno | 4 ++++ 2 files changed, 32 insertions(+) diff --git a/stdlibs/stdlibs.go b/stdlibs/stdlibs.go index b365e43a14e..4660d6d4398 100644 --- a/stdlibs/stdlibs.go +++ b/stdlibs/stdlibs.go @@ -275,6 +275,34 @@ func InjectPackage(store gno.Store, pn *gno.PackageNode) { m.PushValue(res0) }, ) + pn.DefineNative("ExecAsPkg", + // TODO: rename UnsafeExecAsPkg? + gno.Flds( // params + "fn", gno.FuncT(nil, nil), + ), + gno.Flds( // results + ), + func(m *gno.Machine) { + // TODO: limit stack size: 1? 32?. + // TODO: limit usage in goroutines? + // TODO: build a new sub-context instead of patching the root one. + // to support multiple concurrent contexts and advanced flows. + arg0 := m.LastBlock().GetParams1().TV + fn := arg0.GetFunc() + println("#####################", arg0, fn.GetType(m.Store).String()) + //gno.Call(fn, "nil") + //m.Eval(gno.Call(fn)) + // m.Eval(gno.Call(gno.FuncT(nil, nil), fn)) + println("@@@@@@@@@@") + //println(fn) + + /* + ctx := m.Context.(stdlibs.ExecContext) + ctx.OrigCaller = crypto.Bech32Address(addr) + m.Context = ctx + */ + }, + ) pn.DefineNative("GetCallerAt", gno.Flds( // params "n", "int", diff --git a/stdlibs/stdshim/stdshim.gno b/stdlibs/stdshim/stdshim.gno index 3cea10d572d..76544673ed3 100644 --- a/stdlibs/stdshim/stdshim.gno +++ b/stdlibs/stdshim/stdshim.gno @@ -78,3 +78,7 @@ func DecodeBech32(addr Address) (prefix string, bytes [20]byte, ok bool) { func DerivePkgAddr(pkgPath string) (addr Address) { panic(shimWarn) } + +func ExecAsPkg(fn func()) { + panic(shimWarn) +} From 46d14150d28df27ec699d8f3eb1319e95b3ed87f Mon Sep 17 00:00:00 2001 From: Albert Le Batteux Date: Fri, 24 Mar 2023 11:00:49 +0000 Subject: [PATCH 2/3] feat: exec-as-pkg Co-authored-by: Thomas Bruyelle --- pkgs/gnolang/machine.go | 9 +++++++++ pkgs/gnolang/op_call.go | 5 +++++ pkgs/gnolang/values.go | 13 +++++++++++++ stdlibs/stdlibs.go | 36 +++++++++++++++++++++++++----------- tests/file.go | 2 +- tests/files/zrealm_std6.gno | 20 ++++++++++++++++++++ 6 files changed, 73 insertions(+), 12 deletions(-) create mode 100644 tests/files/zrealm_std6.gno diff --git a/pkgs/gnolang/machine.go b/pkgs/gnolang/machine.go index ac39dc2a227..c2d9d000e99 100644 --- a/pkgs/gnolang/machine.go +++ b/pkgs/gnolang/machine.go @@ -804,6 +804,9 @@ const ( OpValueDecl Op = 0x90 // var/const ... OpTypeDecl Op = 0x91 // type ... + /* Context operators */ + OpSetContext Op = 0xA0 + /* Loop (sticky) operators (>= 0xD0) */ OpSticky Op = 0xD0 // not a real op. OpBody Op = 0xD1 // if/block/switch/select. @@ -938,6 +941,9 @@ const ( OpCPUValueDecl = 1 OpCPUTypeDecl = 1 + /* Context operators */ + OpCPUContext = 1 + /* Loop (sticky) operators (>= 0xD0) */ OpCPUSticky = 1 OpCPUBody = 1 @@ -1275,6 +1281,9 @@ func (m *Machine) Run() { case OpReturnCallDefers: m.incrCPU(OpCPUReturnCallDefers) m.doOpReturnCallDefers() + case OpSetContext: + m.incrCPU(OpCPUContext) + m.doOpSetContext() default: panic(fmt.Sprintf("unexpected opcode %s", op.String())) } diff --git a/pkgs/gnolang/op_call.go b/pkgs/gnolang/op_call.go index c6f286dc930..0e4f82fc5af 100644 --- a/pkgs/gnolang/op_call.go +++ b/pkgs/gnolang/op_call.go @@ -407,3 +407,8 @@ func (m *Machine) doOpPanic2() { m.PushOp(OpReturnCallDefers) // XXX rename, not return? } } + +func (m *Machine) doOpSetContext() { + cv := m.PopValue().V.(ContextValue) + m.Context = cv.Context +} diff --git a/pkgs/gnolang/values.go b/pkgs/gnolang/values.go index 227d5368eeb..ce19a9d0d30 100644 --- a/pkgs/gnolang/values.go +++ b/pkgs/gnolang/values.go @@ -40,6 +40,7 @@ func (*PackageValue) assertValue() {} func (*NativeValue) assertValue() {} func (*Block) assertValue() {} func (RefValue) assertValue() {} +func (ContextValue) assertValue() {} const ( nilStr = "nil" @@ -62,6 +63,7 @@ var ( _ Value = &NativeValue{} _ Value = &Block{} _ Value = RefValue{} + _ Value = ContextValue{} ) // ---------------------------------------- @@ -2184,6 +2186,17 @@ func (tv *TypedValue) GetSlice2(alloc *Allocator, low, high, max int) TypedValue } } +// ---------------------------------------- +// ContextValue + +type ContextValue struct { + Context interface{} +} + +func (ctx ContextValue) String() string { + return fmt.Sprintf("%v", ctx.Context) +} + // ---------------------------------------- // Block // diff --git a/stdlibs/stdlibs.go b/stdlibs/stdlibs.go index 4660d6d4398..bd028334086 100644 --- a/stdlibs/stdlibs.go +++ b/stdlibs/stdlibs.go @@ -289,18 +289,32 @@ func InjectPackage(store gno.Store, pn *gno.PackageNode) { // to support multiple concurrent contexts and advanced flows. arg0 := m.LastBlock().GetParams1().TV fn := arg0.GetFunc() - println("#####################", arg0, fn.GetType(m.Store).String()) - //gno.Call(fn, "nil") - //m.Eval(gno.Call(fn)) - // m.Eval(gno.Call(gno.FuncT(nil, nil), fn)) - println("@@@@@@@@@@") - //println(fn) - /* - ctx := m.Context.(stdlibs.ExecContext) - ctx.OrigCaller = crypto.Bech32Address(addr) - m.Context = ctx - */ + ctx := m.Context.(ExecContext) + ctx.OrigCaller = ctx.OrigPkgAddr + + backupContext := m.Context.(ExecContext) + + m.PushValue(gno.TypedValue{ + T: &gno.InterfaceType{}, + V: gno.ContextValue{ + Context: backupContext, + }, + }) + m.PushOp(gno.OpSetContext) + + cx := gno.Call(gno.FuncT(nil, nil)) + m.PushValue(gno.TypedValue{}) + m.PushFrameCall(cx, fn, gno.TypedValue{}) + m.PushOp(gno.OpCall) + + m.PushValue(gno.TypedValue{ + T: &gno.InterfaceType{}, + V: gno.ContextValue{ + Context: ctx, + }, + }) + m.PushOp(gno.OpSetContext) }, ) pn.DefineNative("GetCallerAt", diff --git a/tests/file.go b/tests/file.go index 33afbe38ebb..640e9c55347 100644 --- a/tests/file.go +++ b/tests/file.go @@ -34,7 +34,7 @@ func TestMachine(store gno.Store, stdout io.Writer, pkgPath string) *gno.Machine func testMachineCustom(store gno.Store, pkgPath string, stdout io.Writer, maxAlloc int64, send std.Coins) *gno.Machine { // FIXME: create a better package to manage this, with custom constructors pkgAddr := gno.DerivePkgAddr(pkgPath) // the addr of the pkgPath called. - caller := gno.DerivePkgAddr(pkgPath) // NOTE: for the purpose of testing, the caller is generally the "main" package, same as pkgAddr. + caller := gno.DerivePkgAddr("caller") // NOTE: for the purpose of testing, the caller is generally the "main" package, same as pkgAddr. pkgCoins := std.MustParseCoins("200000000ugnot").Add(send) // >= send. banker := newTestBanker(pkgAddr.Bech32(), pkgCoins) ctx := stdlibs.ExecContext{ diff --git a/tests/files/zrealm_std6.gno b/tests/files/zrealm_std6.gno new file mode 100644 index 00000000000..36a9393b983 --- /dev/null +++ b/tests/files/zrealm_std6.gno @@ -0,0 +1,20 @@ +// PKGPATH: gno.land/r/std_test +package std_test + +import ( + "fmt" + "std" +) + +func main() { + println(std.GetOrigCaller()) + std.ExecAsPkg(func() { + println(std.GetOrigCaller()) + }) + println(std.GetOrigCaller()) +} + +// Output: +// g1fahslvxakc058u0wa98ytfc9fd6trhe5qfh9ld +// g157y5v3k529jyzhjjz4fn49tzzhf4gess6v39xg +// g1fahslvxakc058u0wa98ytfc9fd6trhe5qfh9ld From d59c320fce255e0add72eb2105608cfaac92d59e Mon Sep 17 00:00:00 2001 From: Thomas Bruyelle Date: Fri, 24 Mar 2023 18:51:58 +0100 Subject: [PATCH 3/3] replace OpCall with OpPreCall also add comments and small code reorg --- stdlibs/stdlibs.go | 30 ++++++++++++++---------------- tests/files/zrealm_std6.gno | 12 +++++++----- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/stdlibs/stdlibs.go b/stdlibs/stdlibs.go index bd028334086..849484fe613 100644 --- a/stdlibs/stdlibs.go +++ b/stdlibs/stdlibs.go @@ -287,34 +287,32 @@ func InjectPackage(store gno.Store, pn *gno.PackageNode) { // TODO: limit usage in goroutines? // TODO: build a new sub-context instead of patching the root one. // to support multiple concurrent contexts and advanced flows. - arg0 := m.LastBlock().GetParams1().TV - fn := arg0.GetFunc() - - ctx := m.Context.(ExecContext) - ctx.OrigCaller = ctx.OrigPkgAddr - - backupContext := m.Context.(ExecContext) + // Push original context first, so it will be reset after the function + // call. + m.PushOp(gno.OpSetContext) m.PushValue(gno.TypedValue{ - T: &gno.InterfaceType{}, V: gno.ContextValue{ - Context: backupContext, + Context: m.Context, }, }) - m.PushOp(gno.OpSetContext) - cx := gno.Call(gno.FuncT(nil, nil)) - m.PushValue(gno.TypedValue{}) - m.PushFrameCall(cx, fn, gno.TypedValue{}) - m.PushOp(gno.OpCall) + // Push a function call, to execute the function in parameter. + m.PushOp(gno.OpPrecall) + m.PushExpr(gno.Call(gno.FuncT(nil, nil))) + tv := m.LastBlock().GetParams1().TV + m.PushValue(*tv) + // Push an alternate context with OrigCaller=OrigPkgAddr, this will + // affect the function call above + m.PushOp(gno.OpSetContext) + ctx := m.Context.(ExecContext) + ctx.OrigCaller = ctx.OrigPkgAddr m.PushValue(gno.TypedValue{ - T: &gno.InterfaceType{}, V: gno.ContextValue{ Context: ctx, }, }) - m.PushOp(gno.OpSetContext) }, ) pn.DefineNative("GetCallerAt", diff --git a/tests/files/zrealm_std6.gno b/tests/files/zrealm_std6.gno index 36a9393b983..bed44578594 100644 --- a/tests/files/zrealm_std6.gno +++ b/tests/files/zrealm_std6.gno @@ -6,14 +6,16 @@ import ( "std" ) -func main() { - println(std.GetOrigCaller()) - std.ExecAsPkg(func() { - println(std.GetOrigCaller()) - }) +func printOrigCaller() { println(std.GetOrigCaller()) } +func main() { + printOrigCaller() + std.ExecAsPkg(printOrigCaller) + printOrigCaller() +} + // Output: // g1fahslvxakc058u0wa98ytfc9fd6trhe5qfh9ld // g157y5v3k529jyzhjjz4fn49tzzhf4gess6v39xg