github.com/gnolang/gno@v0.0.0-20240520182011-228e9d0192ce/gnovm/stdlibs/std/native.go (about) 1 package std 2 3 import ( 4 gno "github.com/gnolang/gno/gnovm/pkg/gnolang" 5 "github.com/gnolang/gno/tm2/pkg/bech32" 6 "github.com/gnolang/gno/tm2/pkg/crypto" 7 "github.com/gnolang/gno/tm2/pkg/std" 8 ) 9 10 func AssertOriginCall(m *gno.Machine) { 11 if !IsOriginCall(m) { 12 m.Panic(typedString("invalid non-origin call")) 13 } 14 } 15 16 func IsOriginCall(m *gno.Machine) bool { 17 return len(m.Frames) == 2 18 } 19 20 func CurrentRealmPath(m *gno.Machine) string { 21 if m.Realm != nil { 22 return m.Realm.Path 23 } 24 return "" 25 } 26 27 func GetChainID(m *gno.Machine) string { 28 return m.Context.(ExecContext).ChainID 29 } 30 31 func GetHeight(m *gno.Machine) int64 { 32 return m.Context.(ExecContext).Height 33 } 34 35 // getPrevFunctionNameFromTarget returns the last called function name (identifier) from the call stack. 36 func getPrevFunctionNameFromTarget(m *gno.Machine, targetFunc string) string { 37 targetIndex := findTargetFuncIndex(m, targetFunc) 38 if targetIndex == -1 { 39 return "" 40 } 41 return findPrevFuncName(m, targetIndex) 42 } 43 44 // findTargetFuncIndex finds and returns the index of the target function in the call stack. 45 func findTargetFuncIndex(m *gno.Machine, targetFunc string) int { 46 for i := len(m.Frames) - 1; i >= 0; i-- { 47 currFunc := m.Frames[i].Func 48 if currFunc != nil && currFunc.Name == gno.Name(targetFunc) { 49 return i 50 } 51 } 52 return -1 53 } 54 55 // findPrevFuncName returns the function name before the given index in the call stack. 56 func findPrevFuncName(m *gno.Machine, targetIndex int) string { 57 for i := targetIndex - 1; i >= 0; i-- { 58 currFunc := m.Frames[i].Func 59 if currFunc != nil { 60 return string(currFunc.Name) 61 } 62 } 63 panic("function name not found") 64 } 65 66 func X_origSend(m *gno.Machine) (denoms []string, amounts []int64) { 67 os := m.Context.(ExecContext).OrigSend 68 return ExpandCoins(os) 69 } 70 71 func X_origCaller(m *gno.Machine) string { 72 return string(m.Context.(ExecContext).OrigCaller) 73 } 74 75 func X_origPkgAddr(m *gno.Machine) string { 76 return string(m.Context.(ExecContext).OrigPkgAddr) 77 } 78 79 func X_callerAt(m *gno.Machine, n int) string { 80 if n <= 0 { 81 m.Panic(typedString("GetCallerAt requires positive arg")) 82 return "" 83 } 84 // Add 1 to n to account for the GetCallerAt (gno fn) frame. 85 n++ 86 if n > m.NumFrames() { 87 // NOTE: the last frame's LastPackage 88 // is set to the original non-frame 89 // package, so need this check. 90 m.Panic(typedString("frame not found")) 91 return "" 92 } 93 if n == m.NumFrames() { 94 // This makes it consistent with GetOrigCaller. 95 ctx := m.Context.(ExecContext) 96 return string(ctx.OrigCaller) 97 } 98 return string(m.MustLastCallFrame(n).LastPackage.GetPkgAddr().Bech32()) 99 } 100 101 func X_getRealm(m *gno.Machine, height int) (address string, pkgPath string) { 102 var ( 103 ctx = m.Context.(ExecContext) 104 currentCaller crypto.Bech32Address 105 // Keeps track of the number of times currentCaller 106 // has changed. 107 changes int 108 ) 109 110 for i := m.NumFrames() - 1; i > 0; i-- { 111 fr := m.Frames[i] 112 if fr.LastPackage == nil || !fr.LastPackage.IsRealm() { 113 continue 114 } 115 116 // LastPackage is a realm. Get caller and pkgPath, and compare against 117 // current* values. 118 caller := fr.LastPackage.GetPkgAddr().Bech32() 119 pkgPath := fr.LastPackage.PkgPath 120 if caller != currentCaller { 121 if changes == height { 122 return string(caller), pkgPath 123 } 124 currentCaller = caller 125 changes++ 126 } 127 } 128 129 // Fallback case: return OrigCaller. 130 return string(ctx.OrigCaller), "" 131 } 132 133 func X_derivePkgAddr(pkgPath string) string { 134 return string(gno.DerivePkgAddr(pkgPath).Bech32()) 135 } 136 137 func X_encodeBech32(prefix string, bytes [20]byte) string { 138 b32, err := bech32.ConvertAndEncode(prefix, bytes[:]) 139 if err != nil { 140 panic(err) // should not happen 141 } 142 return b32 143 } 144 145 func X_decodeBech32(addr string) (prefix string, bytes [20]byte, ok bool) { 146 prefix, bz, err := bech32.Decode(addr) 147 if err != nil || len(bz) != 20 { 148 return "", [20]byte{}, false 149 } 150 return prefix, [20]byte(bz), true 151 } 152 153 func typedString(s string) gno.TypedValue { 154 tv := gno.TypedValue{T: gno.StringType} 155 tv.SetString(gno.StringValue(s)) 156 return tv 157 } 158 159 func ExpandCoins(c std.Coins) (denoms []string, amounts []int64) { 160 denoms = make([]string, len(c)) 161 amounts = make([]int64, len(c)) 162 for i, coin := range c { 163 denoms[i] = coin.Denom 164 amounts[i] = coin.Amount 165 } 166 return denoms, amounts 167 } 168 169 func CompactCoins(denoms []string, amounts []int64) std.Coins { 170 coins := make(std.Coins, len(denoms)) 171 for i := range coins { 172 coins[i] = std.Coin{Denom: denoms[i], Amount: amounts[i]} 173 } 174 return coins 175 }