From d63918fe42e578bae037fa7a4987ed445804fa89 Mon Sep 17 00:00:00 2001 From: ltzmaxwell Date: Tue, 15 Oct 2024 20:59:39 +0800 Subject: [PATCH 1/7] fix(gnovm): correct type for shift expression (#1775) [shift operator where first operand is an untyped bigint always results in a bigint](https://github.com/gnolang/gno/issues/1462) is not resolved by #1426, it's fixed by this one. ================================================================= 1. This is a fix to gnolang/gno/issues/1462; 3. **NOTE**: This PR should be reviewed following the potential merger of #1426, from which it is both decoupled and dependent. #1426 serves as base branch of this one. 4. **NOTE**: Currently, this PR displays all code including that from #1426, because it is being compared to the master branch instead of differing against #1426 directly. --------- Co-authored-by: Morgan Co-authored-by: Marc Vertes --- gnovm/pkg/gnolang/eval_test.go | 4 +- gnovm/pkg/gnolang/nodes.go | 1 + gnovm/pkg/gnolang/op_binary.go | 2 + gnovm/pkg/gnolang/op_call.go | 5 + gnovm/pkg/gnolang/preprocess.go | 194 ++++++++++++++---- gnovm/pkg/gnolang/type_check.go | 121 ++++++++--- gnovm/pkg/gnolang/values.go | 106 ++++------ gnovm/pkg/gnolang/values_conversions.go | 1 + gnovm/tests/files/types/cmp_slice.gno | 14 ++ .../files/types/explicit_conversion_0.gno | 13 ++ .../files/types/explicit_conversion_1.gno | 13 ++ .../files/types/explicit_conversion_2.gno | 14 ++ .../files/types/explicit_conversion_4.gno | 9 + .../files/types/explicit_conversion_5.gno | 9 + gnovm/tests/files/types/shift_a11.gno | 2 +- gnovm/tests/files/types/shift_a2.gno | 1 - gnovm/tests/files/types/shift_a4.gno | 1 - gnovm/tests/files/types/shift_a5.gno | 6 +- gnovm/tests/files/types/shift_a7.gno | 2 +- gnovm/tests/files/types/shift_b0.gno | 14 ++ gnovm/tests/files/types/shift_b1.gno | 14 ++ gnovm/tests/files/types/shift_b10.gno | 14 ++ gnovm/tests/files/types/shift_b11.gno | 14 ++ gnovm/tests/files/types/shift_b2.gno | 14 ++ gnovm/tests/files/types/shift_b3.gno | 32 +++ gnovm/tests/files/types/shift_b4.gno | 32 +++ gnovm/tests/files/types/shift_b5.gno | 31 +++ gnovm/tests/files/types/shift_b6.gno | 30 +++ gnovm/tests/files/types/shift_b6a.gno | 31 +++ gnovm/tests/files/types/shift_b7.gno | 13 ++ gnovm/tests/files/types/shift_b8.gno | 14 ++ gnovm/tests/files/types/shift_b9.gno | 14 ++ gnovm/tests/files/types/shift_c10.gno | 12 ++ gnovm/tests/files/types/shift_c3.gno | 14 ++ gnovm/tests/files/types/shift_c4.gno | 14 ++ gnovm/tests/files/types/shift_c5.gno | 10 + gnovm/tests/files/types/shift_c6.gno | 14 ++ gnovm/tests/files/types/shift_c7.gno | 14 ++ gnovm/tests/files/types/shift_c8.gno | 14 ++ gnovm/tests/files/types/shift_c9.gno | 14 ++ gnovm/tests/files/types/shift_d11.gno | 21 ++ gnovm/tests/files/types/shift_d12.gno | 16 ++ gnovm/tests/files/types/shift_d13.gno | 17 ++ gnovm/tests/files/types/shift_d14.gno | 18 ++ gnovm/tests/files/types/shift_d15.gno | 10 + gnovm/tests/files/types/shift_d16.gno | 10 + gnovm/tests/files/types/shift_d21.gno | 10 + gnovm/tests/files/types/shift_d24.gno | 10 + gnovm/tests/files/types/shift_d25.gno | 10 + gnovm/tests/files/types/shift_d26.gno | 11 + gnovm/tests/files/types/shift_d27.gno | 11 + gnovm/tests/files/types/shift_d28.gno | 11 + gnovm/tests/files/types/shift_d29.gno | 14 ++ gnovm/tests/files/types/shift_d3.gno | 9 + gnovm/tests/files/types/shift_d30.gno | 14 ++ gnovm/tests/files/types/shift_d32.gno | 14 ++ gnovm/tests/files/types/shift_d32a.gno | 13 ++ gnovm/tests/files/types/shift_d33.gno | 14 ++ gnovm/tests/files/types/shift_d34.gno | 13 ++ gnovm/tests/files/types/shift_d35.gno | 14 ++ gnovm/tests/files/types/shift_d36.gno | 14 ++ gnovm/tests/files/types/shift_d37.gno | 9 + gnovm/tests/files/types/shift_d38.gno | 8 + gnovm/tests/files/types/shift_d39.gno | 16 ++ gnovm/tests/files/types/shift_d4.gno | 9 + gnovm/tests/files/types/shift_d40.gno | 10 + gnovm/tests/files/types/shift_d41.gno | 10 + gnovm/tests/files/types/shift_d42.gno | 14 ++ gnovm/tests/files/types/shift_d43.gno | 10 + gnovm/tests/files/types/shift_d44.gno | 10 + gnovm/tests/files/types/shift_d45.gno | 10 + gnovm/tests/files/types/shift_d46.gno | 10 + gnovm/tests/files/types/shift_d47.gno | 26 +++ gnovm/tests/files/types/shift_d48.gno | 23 +++ gnovm/tests/files/types/shift_d4a.gno | 9 + gnovm/tests/files/types/shift_d5.gno | 10 + gnovm/tests/files/types/shift_d50.gno | 13 ++ gnovm/tests/files/types/shift_d51.gno | 10 + gnovm/tests/files/types/shift_d52.gno | 10 + gnovm/tests/files/types/shift_d53.gno | 12 ++ gnovm/tests/files/types/shift_d54.gno | 14 ++ gnovm/tests/files/types/shift_d55.gno | 16 ++ gnovm/tests/files/types/shift_d56.gno | 16 ++ gnovm/tests/files/types/shift_d5a.gno | 10 + gnovm/tests/files/types/shift_d5b.gno | 10 + gnovm/tests/files/types/shift_d6.gno | 18 ++ gnovm/tests/files/types/shift_d9.gno | 9 + gnovm/tests/files/types/shift_e0.gno | 8 + gnovm/tests/files/types/shift_e1.gno | 8 + gnovm/tests/files/types/shift_e1a.gno | 8 + gnovm/tests/files/types/shift_e2.gno | 8 + gnovm/tests/files/types/shift_e3.gno | 9 + gnovm/tests/files/types/shift_e4.gno | 9 + gnovm/tests/files/types/shift_e5.gno | 9 + gnovm/tests/files/types/shift_e6.gno | 9 + gnovm/tests/files/types/shift_e7.gno | 9 + gnovm/tests/files/types/shift_e7a.gno | 9 + gnovm/tests/files/types/shift_e7b.gno | 8 + gnovm/tests/files/types/shift_e8.gno | 9 + gnovm/tests/files/types/shift_e9.gno | 11 + gnovm/tests/files/types/shift_e9a.gno | 11 + gnovm/tests/files/types/shift_f1a.gno | 12 ++ gnovm/tests/files/types/shift_f1b.gno | 12 ++ gnovm/tests/files/types/shift_f2.gno | 10 + gnovm/tests/files/types/shift_f2a.gno | 10 + gnovm/tests/files/types/shift_f2b.gno | 10 + gnovm/tests/files/types/shift_f2c.gno | 10 + gnovm/tests/files/types/shift_f2d.gno | 10 + gnovm/tests/files/types/shift_f2e.gno | 10 + gnovm/tests/files/types/shift_f3.gno | 10 + gnovm/tests/files/types/shift_f3a.gno | 10 + gnovm/tests/files/types/shift_f3b.gno | 10 + gnovm/tests/files/types/shift_f3c.gno | 10 + gnovm/tests/files/types/shift_f3d.gno | 10 + gnovm/tests/files/types/shift_f4.gno | 10 + gnovm/tests/files/types/shift_f5.gno | 10 + gnovm/tests/files/types/shift_g.gno | 18 ++ 117 files changed, 1640 insertions(+), 144 deletions(-) create mode 100644 gnovm/tests/files/types/cmp_slice.gno create mode 100644 gnovm/tests/files/types/explicit_conversion_0.gno create mode 100644 gnovm/tests/files/types/explicit_conversion_1.gno create mode 100644 gnovm/tests/files/types/explicit_conversion_2.gno create mode 100644 gnovm/tests/files/types/explicit_conversion_4.gno create mode 100644 gnovm/tests/files/types/explicit_conversion_5.gno create mode 100644 gnovm/tests/files/types/shift_b0.gno create mode 100644 gnovm/tests/files/types/shift_b1.gno create mode 100644 gnovm/tests/files/types/shift_b10.gno create mode 100644 gnovm/tests/files/types/shift_b11.gno create mode 100644 gnovm/tests/files/types/shift_b2.gno create mode 100644 gnovm/tests/files/types/shift_b3.gno create mode 100644 gnovm/tests/files/types/shift_b4.gno create mode 100644 gnovm/tests/files/types/shift_b5.gno create mode 100644 gnovm/tests/files/types/shift_b6.gno create mode 100644 gnovm/tests/files/types/shift_b6a.gno create mode 100644 gnovm/tests/files/types/shift_b7.gno create mode 100644 gnovm/tests/files/types/shift_b8.gno create mode 100644 gnovm/tests/files/types/shift_b9.gno create mode 100644 gnovm/tests/files/types/shift_c10.gno create mode 100644 gnovm/tests/files/types/shift_c3.gno create mode 100644 gnovm/tests/files/types/shift_c4.gno create mode 100644 gnovm/tests/files/types/shift_c5.gno create mode 100644 gnovm/tests/files/types/shift_c6.gno create mode 100644 gnovm/tests/files/types/shift_c7.gno create mode 100644 gnovm/tests/files/types/shift_c8.gno create mode 100644 gnovm/tests/files/types/shift_c9.gno create mode 100644 gnovm/tests/files/types/shift_d11.gno create mode 100644 gnovm/tests/files/types/shift_d12.gno create mode 100644 gnovm/tests/files/types/shift_d13.gno create mode 100644 gnovm/tests/files/types/shift_d14.gno create mode 100644 gnovm/tests/files/types/shift_d15.gno create mode 100644 gnovm/tests/files/types/shift_d16.gno create mode 100644 gnovm/tests/files/types/shift_d21.gno create mode 100644 gnovm/tests/files/types/shift_d24.gno create mode 100644 gnovm/tests/files/types/shift_d25.gno create mode 100644 gnovm/tests/files/types/shift_d26.gno create mode 100644 gnovm/tests/files/types/shift_d27.gno create mode 100644 gnovm/tests/files/types/shift_d28.gno create mode 100644 gnovm/tests/files/types/shift_d29.gno create mode 100644 gnovm/tests/files/types/shift_d3.gno create mode 100644 gnovm/tests/files/types/shift_d30.gno create mode 100644 gnovm/tests/files/types/shift_d32.gno create mode 100644 gnovm/tests/files/types/shift_d32a.gno create mode 100644 gnovm/tests/files/types/shift_d33.gno create mode 100644 gnovm/tests/files/types/shift_d34.gno create mode 100644 gnovm/tests/files/types/shift_d35.gno create mode 100644 gnovm/tests/files/types/shift_d36.gno create mode 100644 gnovm/tests/files/types/shift_d37.gno create mode 100644 gnovm/tests/files/types/shift_d38.gno create mode 100644 gnovm/tests/files/types/shift_d39.gno create mode 100644 gnovm/tests/files/types/shift_d4.gno create mode 100644 gnovm/tests/files/types/shift_d40.gno create mode 100644 gnovm/tests/files/types/shift_d41.gno create mode 100644 gnovm/tests/files/types/shift_d42.gno create mode 100644 gnovm/tests/files/types/shift_d43.gno create mode 100644 gnovm/tests/files/types/shift_d44.gno create mode 100644 gnovm/tests/files/types/shift_d45.gno create mode 100644 gnovm/tests/files/types/shift_d46.gno create mode 100644 gnovm/tests/files/types/shift_d47.gno create mode 100644 gnovm/tests/files/types/shift_d48.gno create mode 100644 gnovm/tests/files/types/shift_d4a.gno create mode 100644 gnovm/tests/files/types/shift_d5.gno create mode 100644 gnovm/tests/files/types/shift_d50.gno create mode 100644 gnovm/tests/files/types/shift_d51.gno create mode 100644 gnovm/tests/files/types/shift_d52.gno create mode 100644 gnovm/tests/files/types/shift_d53.gno create mode 100644 gnovm/tests/files/types/shift_d54.gno create mode 100644 gnovm/tests/files/types/shift_d55.gno create mode 100644 gnovm/tests/files/types/shift_d56.gno create mode 100644 gnovm/tests/files/types/shift_d5a.gno create mode 100644 gnovm/tests/files/types/shift_d5b.gno create mode 100644 gnovm/tests/files/types/shift_d6.gno create mode 100644 gnovm/tests/files/types/shift_d9.gno create mode 100644 gnovm/tests/files/types/shift_e0.gno create mode 100644 gnovm/tests/files/types/shift_e1.gno create mode 100644 gnovm/tests/files/types/shift_e1a.gno create mode 100644 gnovm/tests/files/types/shift_e2.gno create mode 100644 gnovm/tests/files/types/shift_e3.gno create mode 100644 gnovm/tests/files/types/shift_e4.gno create mode 100644 gnovm/tests/files/types/shift_e5.gno create mode 100644 gnovm/tests/files/types/shift_e6.gno create mode 100644 gnovm/tests/files/types/shift_e7.gno create mode 100644 gnovm/tests/files/types/shift_e7a.gno create mode 100644 gnovm/tests/files/types/shift_e7b.gno create mode 100644 gnovm/tests/files/types/shift_e8.gno create mode 100644 gnovm/tests/files/types/shift_e9.gno create mode 100644 gnovm/tests/files/types/shift_e9a.gno create mode 100644 gnovm/tests/files/types/shift_f1a.gno create mode 100644 gnovm/tests/files/types/shift_f1b.gno create mode 100644 gnovm/tests/files/types/shift_f2.gno create mode 100644 gnovm/tests/files/types/shift_f2a.gno create mode 100644 gnovm/tests/files/types/shift_f2b.gno create mode 100644 gnovm/tests/files/types/shift_f2c.gno create mode 100644 gnovm/tests/files/types/shift_f2d.gno create mode 100644 gnovm/tests/files/types/shift_f2e.gno create mode 100644 gnovm/tests/files/types/shift_f3.gno create mode 100644 gnovm/tests/files/types/shift_f3a.gno create mode 100644 gnovm/tests/files/types/shift_f3b.gno create mode 100644 gnovm/tests/files/types/shift_f3c.gno create mode 100644 gnovm/tests/files/types/shift_f3d.gno create mode 100644 gnovm/tests/files/types/shift_f4.gno create mode 100644 gnovm/tests/files/types/shift_f5.gno create mode 100644 gnovm/tests/files/types/shift_g.gno diff --git a/gnovm/pkg/gnolang/eval_test.go b/gnovm/pkg/gnolang/eval_test.go index 9acf4cc89f0..9b83d673767 100644 --- a/gnovm/pkg/gnolang/eval_test.go +++ b/gnovm/pkg/gnolang/eval_test.go @@ -40,8 +40,8 @@ func TestEvalFiles(t *testing.T) { if wantStacktrace != "" && !strings.Contains(stacktrace, wantStacktrace) { t.Fatalf("unexpected stacktrace\nWant: %s\n Got: %s", wantStacktrace, stacktrace) } - if wantOut != "" && out != wantOut { - t.Fatalf("unexpected output\nWant: %s\n Got: %s", wantOut, out) + if wantOut != "" && strings.TrimSpace(out) != strings.TrimSpace(wantOut) { + t.Fatalf("unexpected output\nWant: \"%s\"\n Got: \"%s\"", wantOut, out) } }) diff --git a/gnovm/pkg/gnolang/nodes.go b/gnovm/pkg/gnolang/nodes.go index b18ed157ca6..8927eafcfb2 100644 --- a/gnovm/pkg/gnolang/nodes.go +++ b/gnovm/pkg/gnolang/nodes.go @@ -2119,6 +2119,7 @@ const ( ATTR_IOTA GnoAttribute = "ATTR_IOTA" ATTR_LOCATIONED GnoAttribute = "ATTR_LOCATIONED" ATTR_INJECTED GnoAttribute = "ATTR_INJECTED" + ATTR_SHIFT_RHS GnoAttribute = "ATTR_SHIFT_RHS" ) var rePkgName = regexp.MustCompile(`^[a-z][a-z0-9_]+$`) diff --git a/gnovm/pkg/gnolang/op_binary.go b/gnovm/pkg/gnolang/op_binary.go index db3c1e5695c..24123d285ad 100644 --- a/gnovm/pkg/gnolang/op_binary.go +++ b/gnovm/pkg/gnolang/op_binary.go @@ -1097,6 +1097,7 @@ func xorAssign(lv, rv *TypedValue) { // for doOpShl and doOpShlAssign. func shlAssign(lv, rv *TypedValue) { + rv.AssertNonNegative("runtime error: negative shift amount") // set the result in lv. // NOTE: baseOf(rv.T) is always UintType. switch baseOf(lv.T) { @@ -1136,6 +1137,7 @@ func shlAssign(lv, rv *TypedValue) { // for doOpShr and doOpShrAssign. func shrAssign(lv, rv *TypedValue) { + rv.AssertNonNegative("runtime error: negative shift amount") // set the result in lv. // NOTE: baseOf(rv.T) is always UintType. switch baseOf(lv.T) { diff --git a/gnovm/pkg/gnolang/op_call.go b/gnovm/pkg/gnolang/op_call.go index 15531ec610d..510c308a86a 100644 --- a/gnovm/pkg/gnolang/op_call.go +++ b/gnovm/pkg/gnolang/op_call.go @@ -27,6 +27,11 @@ func (m *Machine) doOpPrecall() { case TypeValue: // Do not pop type yet. // No need for frames. + xv := m.PeekValue(1) + if cx.GetAttribute(ATTR_SHIFT_RHS) == true { + xv.AssertNonNegative("runtime error: negative shift amount") + } + m.PushOp(OpConvert) if debug { if len(cx.Args) != 1 { diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 9168fc6f7c1..df1f7bab498 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -1025,7 +1025,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { isShift := n.Op == SHL || n.Op == SHR if isShift { // check LHS type compatibility - n.checkShiftLhs(lt) + n.assertShiftExprCompatible1(store, last, lt, rt) // checkOrConvert RHS if baseOf(rt) != UintType { // convert n.Right to (gno) uint type, @@ -1036,6 +1036,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { Op: n.Op, Right: rn, } + n2.Right.SetAttribute(ATTR_SHIFT_RHS, true) resn := Preprocess(store, last, n2) return resn, TRANS_CONTINUE } @@ -1097,12 +1098,34 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // NOTE: binary operations are always computed in // gno, never with reflect. } else { - // convert n.Left to right type. - checkOrConvertType(store, last, &n.Left, rt, false) + // right is untyped const, left is not const, typed/untyped + checkUntypedShiftExpr := func(x Expr) { + if bx, ok := x.(*BinaryExpr); ok { + slt := evalStaticTypeOf(store, last, bx.Left) + if bx.Op == SHL || bx.Op == SHR { + srt := evalStaticTypeOf(store, last, bx.Right) + bx.assertShiftExprCompatible1(store, last, slt, srt) + } + } + } + + if !isUntyped(rt) { // right is typed + checkOrConvertType(store, last, &n.Left, rt, false) + } else { + if shouldSwapOnSpecificity(lt, rt) { + checkUntypedShiftExpr(n.Right) + } else { + checkUntypedShiftExpr(n.Left) + } + } } } else if lcx.T == nil { // LHS is nil. // convert n.Left to typed-nil type. checkOrConvertType(store, last, &n.Left, rt, false) + } else { + if isUntyped(rt) { + checkOrConvertType(store, last, &n.Right, lt, false) + } } } else if ric { // right is const, left is not if isUntyped(rcx.T) { @@ -1134,12 +1157,33 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // NOTE: binary operations are always computed in // gno, never with reflect. } else { - // convert n.Right to left type. - checkOrConvertType(store, last, &n.Right, lt, false) + // right is untyped const, left is not const, typed or untyped + checkUntypedShiftExpr := func(x Expr) { + if bx, ok := x.(*BinaryExpr); ok { + if bx.Op == SHL || bx.Op == SHR { + srt := evalStaticTypeOf(store, last, bx.Right) + bx.assertShiftExprCompatible1(store, last, rt, srt) + } + } + } + // both untyped, e.g. 1<>=. convertType(store, last, &n.Rhs[0], UintType) } else if n.Op == ADD_ASSIGN || n.Op == SUB_ASSIGN || n.Op == MUL_ASSIGN || n.Op == QUO_ASSIGN || n.Op == REM_ASSIGN { @@ -2281,10 +2343,15 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { vt := evalStaticTypeOf(store, last, vx) sts[i] = vt } - } else { + } else { // T is nil, n not const // convert n.Value to default type. for i, vx := range n.Values { - convertIfConst(store, last, vx) + if cx, ok := vx.(*ConstExpr); ok { + convertConst(store, last, cx, nil) + // convertIfConst(store, last, vx) + } else { + checkOrConvertType(store, last, &vx, nil, false) + } vt := evalStaticTypeOf(store, last, vx) sts[i] = vt } @@ -2840,9 +2907,25 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative assertAssignableTo(cx.T, t, autoNative) } } else if bx, ok := (*x).(*BinaryExpr); ok && (bx.Op == SHL || bx.Op == SHR) { - // "push" expected type into shift binary's left operand. recursively. - checkOrConvertType(store, last, &bx.Left, t, autoNative) - } else if *x != nil { // XXX if x != nil && t != nil { + xt := evalStaticTypeOf(store, last, *x) + if debug { + debug.Printf("shift, xt: %v, Op: %v, t: %v \n", xt, bx.Op, t) + } + if isUntyped(xt) { + // check assignable first, see: types/shift_b6.gno + assertAssignableTo(xt, t, autoNative) + + if t == nil || t.Kind() == InterfaceKind { + t = defaultTypeOf(xt) + } + + bx.assertShiftExprCompatible2(t) + checkOrConvertType(store, last, &bx.Left, t, autoNative) + } else { + assertAssignableTo(xt, t, autoNative) + } + return + } else if *x != nil { xt := evalStaticTypeOf(store, last, *x) if t != nil { assertAssignableTo(xt, t, autoNative) @@ -2853,19 +2936,53 @@ func checkOrConvertType(store Store, last BlockNode, x *Expr, t Type, autoNative switch bx.Op { case ADD, SUB, MUL, QUO, REM, BAND, BOR, XOR, BAND_NOT, LAND, LOR: - // push t into bx.Left and bx.Right - checkOrConvertType(store, last, &bx.Left, t, autoNative) - checkOrConvertType(store, last, &bx.Right, t, autoNative) - return - case SHL, SHR: - // push t into bx.Left - checkOrConvertType(store, last, &bx.Left, t, autoNative) + lt := evalStaticTypeOf(store, last, bx.Left) + rt := evalStaticTypeOf(store, last, bx.Right) + if t != nil { + // push t into bx.Left and bx.Right + checkOrConvertType(store, last, &bx.Left, t, autoNative) + checkOrConvertType(store, last, &bx.Right, t, autoNative) + return + } else { + if shouldSwapOnSpecificity(lt, rt) { + // e.g. 1.0< string)) to type uint diff --git a/gnovm/tests/files/types/shift_a2.gno b/gnovm/tests/files/types/shift_a2.gno index 91072929306..726d5415b15 100644 --- a/gnovm/tests/files/types/shift_a2.gno +++ b/gnovm/tests/files/types/shift_a2.gno @@ -1,6 +1,5 @@ package main -// both typed(different) const func main() { println(1 << int(1)) println(1 >> int(1)) diff --git a/gnovm/tests/files/types/shift_a4.gno b/gnovm/tests/files/types/shift_a4.gno index 3561929b672..694d771f190 100644 --- a/gnovm/tests/files/types/shift_a4.gno +++ b/gnovm/tests/files/types/shift_a4.gno @@ -1,6 +1,5 @@ package main -// both typed(different) const func main() { println(1 << 1.0) println(1 >> 1.0) diff --git a/gnovm/tests/files/types/shift_a5.gno b/gnovm/tests/files/types/shift_a5.gno index a0b7652c6d1..5d2c4304732 100644 --- a/gnovm/tests/files/types/shift_a5.gno +++ b/gnovm/tests/files/types/shift_a5.gno @@ -1,10 +1,10 @@ package main -// TODO: support this? func main() { println(1.0 << 1) println(1.0 >> 1) } -// Error: -// main/files/types/shift_a5.gno:5:10: operator << not defined on: BigdecKind +// Output: +// 2 +// 0 diff --git a/gnovm/tests/files/types/shift_a7.gno b/gnovm/tests/files/types/shift_a7.gno index 62151c5cfc5..cd1b3d95ec7 100644 --- a/gnovm/tests/files/types/shift_a7.gno +++ b/gnovm/tests/files/types/shift_a7.gno @@ -6,4 +6,4 @@ func main() { } // Error: -// main/files/types/shift_a7.gno:3:1: cannot convert StringKind to UintKind +// main/files/types/shift_a7.gno:5:10: cannot convert (const ("a" string)) to type uint diff --git a/gnovm/tests/files/types/shift_b0.gno b/gnovm/tests/files/types/shift_b0.gno new file mode 100644 index 00000000000..fa9ee4ed2a0 --- /dev/null +++ b/gnovm/tests/files/types/shift_b0.gno @@ -0,0 +1,14 @@ +package main + +import "fmt" + +func main() { + x := 2 + r := uint64(1 << x) + println(r) + fmt.Printf("%T \n", r) +} + +// Output: +// 4 +// uint64 diff --git a/gnovm/tests/files/types/shift_b1.gno b/gnovm/tests/files/types/shift_b1.gno new file mode 100644 index 00000000000..403887269c0 --- /dev/null +++ b/gnovm/tests/files/types/shift_b1.gno @@ -0,0 +1,14 @@ +package main + +import "fmt" + +func main() { + x := 2 + r := uint64(1< bigint does not implement main.R (missing method foo) diff --git a/gnovm/tests/files/types/shift_b6a.gno b/gnovm/tests/files/types/shift_b6a.gno new file mode 100644 index 00000000000..26b7f1b2ea1 --- /dev/null +++ b/gnovm/tests/files/types/shift_b6a.gno @@ -0,0 +1,31 @@ +package main + +import "fmt" + +type R interface { + foo() +} + +type U64 uint64 + +func (u64 U64) foo() { + println("bar") +} + +func bar(r R) { + r.foo() +} + +func main() { + x := 2 + var r R + r = U64(1) << x + + r.foo() + + fmt.Printf("%T \n", r) // TODO: should output main.U64 rather than the underlying type +} + +// Output: +// bar +// uint64 diff --git a/gnovm/tests/files/types/shift_b7.gno b/gnovm/tests/files/types/shift_b7.gno new file mode 100644 index 00000000000..ccc6cd41b7f --- /dev/null +++ b/gnovm/tests/files/types/shift_b7.gno @@ -0,0 +1,13 @@ +package main + +import "fmt" + +func main() { + x := 2 + r := float32(1<>2) +} + +// Output: +// 4 0 diff --git a/gnovm/tests/files/types/shift_c3.gno b/gnovm/tests/files/types/shift_c3.gno new file mode 100644 index 00000000000..6ca9a8b7cc2 --- /dev/null +++ b/gnovm/tests/files/types/shift_c3.gno @@ -0,0 +1,14 @@ +package main + +import "fmt" + +func main() { + x := 1 + r := uint(+(1 << x)) + println(r) + fmt.Printf("%T \n", r) +} + +// Output: +// 2 +// uint diff --git a/gnovm/tests/files/types/shift_c4.gno b/gnovm/tests/files/types/shift_c4.gno new file mode 100644 index 00000000000..55b5fa782d7 --- /dev/null +++ b/gnovm/tests/files/types/shift_c4.gno @@ -0,0 +1,14 @@ +package main + +import "fmt" + +func main() { + x := 63 + r := int32(+(1<>x) +} + +// Output: +// uint64 +// int64 +// 2048 +// 0 diff --git a/gnovm/tests/files/types/shift_d12.gno b/gnovm/tests/files/types/shift_d12.gno new file mode 100644 index 00000000000..3d8c6e3de16 --- /dev/null +++ b/gnovm/tests/files/types/shift_d12.gno @@ -0,0 +1,16 @@ +package main + +import "fmt" + +func foo(a uint64, b float32) { + fmt.Printf("%T \n", a) + println(a) +} + +func main() { + x := 11 + foo(1<>x) +} + +// Error: +// main/files/types/shift_d12.gno:12:2: operator >> not defined on: Float32Kind diff --git a/gnovm/tests/files/types/shift_d13.gno b/gnovm/tests/files/types/shift_d13.gno new file mode 100644 index 00000000000..0ab495c1a26 --- /dev/null +++ b/gnovm/tests/files/types/shift_d13.gno @@ -0,0 +1,17 @@ +package main + +import "fmt" + +// it's like assign +func foo(a uint64, b float32) { + fmt.Printf("%T \n", a) + println(a) +} + +func main() { + x := 11 + foo(1<>x) +} + +// Error: +// main/files/types/shift_d13.gno:13:2: cannot use int as float32 diff --git a/gnovm/tests/files/types/shift_d14.gno b/gnovm/tests/files/types/shift_d14.gno new file mode 100644 index 00000000000..8458cf94ffb --- /dev/null +++ b/gnovm/tests/files/types/shift_d14.gno @@ -0,0 +1,18 @@ +package main + +import "fmt" + +// it's like assign +func foo(a uint64, b int64) { + fmt.Printf("%T\n", a) + println(a) +} + +func main() { + x := 11 + foo(1<>x) +} + +// Output: +// uint64 +// 2048 diff --git a/gnovm/tests/files/types/shift_d15.gno b/gnovm/tests/files/types/shift_d15.gno new file mode 100644 index 00000000000..a29108aef5a --- /dev/null +++ b/gnovm/tests/files/types/shift_d15.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 64 + y := uint64(1 << x) + println(y) +} + +// Output: +// 0 diff --git a/gnovm/tests/files/types/shift_d16.gno b/gnovm/tests/files/types/shift_d16.gno new file mode 100644 index 00000000000..3b7fb0aec50 --- /dev/null +++ b/gnovm/tests/files/types/shift_d16.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 64 + y := uint64(1<>2) //special case with == !=, untyped bool + println(r) +} + +// Error: +// main/files/types/shift_d4.gno:4:7: cannot convert BoolKind to Uint64Kind diff --git a/gnovm/tests/files/types/shift_d40.gno b/gnovm/tests/files/types/shift_d40.gno new file mode 100644 index 00000000000..8840f8b7322 --- /dev/null +++ b/gnovm/tests/files/types/shift_d40.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 2 + s := []float32{1 << a} + println(s[0]) +} + +// Error: +// main/files/types/shift_d40.gno:5:7: operator << not defined on: Float32Kind diff --git a/gnovm/tests/files/types/shift_d41.gno b/gnovm/tests/files/types/shift_d41.gno new file mode 100644 index 00000000000..bf46da524f7 --- /dev/null +++ b/gnovm/tests/files/types/shift_d41.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 2 + s := map[string]float32{"k": 1 << a} + println(s["k"]) +} + +// Error: +// main/files/types/shift_d41.gno:5:7: operator << not defined on: Float32Kind diff --git a/gnovm/tests/files/types/shift_d42.gno b/gnovm/tests/files/types/shift_d42.gno new file mode 100644 index 00000000000..c2bbfe94e2b --- /dev/null +++ b/gnovm/tests/files/types/shift_d42.gno @@ -0,0 +1,14 @@ +package main + +func main() { + type S struct { + a float32 + } + s := S{ + a: 1 << 2, + } + println(s.a) +} + +// Output: +// 4 diff --git a/gnovm/tests/files/types/shift_d43.gno b/gnovm/tests/files/types/shift_d43.gno new file mode 100644 index 00000000000..e9b0032ac9a --- /dev/null +++ b/gnovm/tests/files/types/shift_d43.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 2 + s := map[string]interface{}{"k": 1 << a} + println(s["k"]) +} + +// Output: +// 4 diff --git a/gnovm/tests/files/types/shift_d44.gno b/gnovm/tests/files/types/shift_d44.gno new file mode 100644 index 00000000000..0ef024f1e6b --- /dev/null +++ b/gnovm/tests/files/types/shift_d44.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 1 + b := 1 + (a == b)++ // LHS is untyped bool, determined in preprocess +} + +// Error: +// main/files/types/shift_d44.gno:6:2: operator ++ not defined on: BoolKind diff --git a/gnovm/tests/files/types/shift_d45.gno b/gnovm/tests/files/types/shift_d45.gno new file mode 100644 index 00000000000..5c504d7d616 --- /dev/null +++ b/gnovm/tests/files/types/shift_d45.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 11 + y := uint64(1 << x) + println(y) +} + +// Output: +// 2048 diff --git a/gnovm/tests/files/types/shift_d46.gno b/gnovm/tests/files/types/shift_d46.gno new file mode 100644 index 00000000000..8490c751c88 --- /dev/null +++ b/gnovm/tests/files/types/shift_d46.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 11 + y := uint64(1.0 << x) + println(y) +} + +// Output: +// 2048 diff --git a/gnovm/tests/files/types/shift_d47.gno b/gnovm/tests/files/types/shift_d47.gno new file mode 100644 index 00000000000..d50c3944e90 --- /dev/null +++ b/gnovm/tests/files/types/shift_d47.gno @@ -0,0 +1,26 @@ +package main + +var specialBytes [16]byte + +func main() { + for i, b := range []byte(`\.+*?()|[]{}^$`) { + specialBytes[b%16] |= 1 << (b / 16) + println(i, (1 << (b / 16)), specialBytes[b%16]) + } +} + +// Output: +// 0 32 32 +// 1 4 4 +// 2 4 4 +// 3 4 4 +// 4 8 8 +// 5 4 4 +// 6 4 4 +// 7 128 160 +// 8 32 36 +// 9 32 32 +// 10 128 164 +// 11 128 160 +// 12 32 36 +// 13 4 4 diff --git a/gnovm/tests/files/types/shift_d48.gno b/gnovm/tests/files/types/shift_d48.gno new file mode 100644 index 00000000000..2ec6782c7f0 --- /dev/null +++ b/gnovm/tests/files/types/shift_d48.gno @@ -0,0 +1,23 @@ +package main + +import ( + "github.com/gnolang/gno/_test/net/http" +) + +type extendedRequest struct { + Request http.Request + + Data string +} + +func main() { + r := extendedRequest{} + // req := &r.Request + + println(r) + // XXX removed temporarily until recursion detection implemented for sprintString(). + // println(req) +} + +// Output: +// (struct{(struct{( string),( string),(0 int),(0 int),(nil github.com/gnolang/gno/_test/net/http.Header),(undefined),(0 int64),(nil []string),(false bool),( string),(nil github.com/gnolang/gno/_test/net/http.Values),(nil github.com/gnolang/gno/_test/net/http.Values),(nil github.com/gnolang/gno/_test/net/http.Header),( string),( string),(nil *github.com/gnolang/gno/_test/net/http.Response)} github.com/gnolang/gno/_test/net/http.Request),( string)} main.extendedRequest) diff --git a/gnovm/tests/files/types/shift_d4a.gno b/gnovm/tests/files/types/shift_d4a.gno new file mode 100644 index 00000000000..803da33ea64 --- /dev/null +++ b/gnovm/tests/files/types/shift_d4a.gno @@ -0,0 +1,9 @@ +package main + +func main() { + r := string(1<<2 == 1>>2) //special case with == !=, untyped bool + println(r) +} + +// Error: +// main/files/types/shift_d4a.gno:4:7: cannot convert BoolKind to StringKind diff --git a/gnovm/tests/files/types/shift_d5.gno b/gnovm/tests/files/types/shift_d5.gno new file mode 100644 index 00000000000..43c0e117f5e --- /dev/null +++ b/gnovm/tests/files/types/shift_d5.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 11 + y := 1.0 << x // no const + println(y) +} + +// Error: +// main/files/types/shift_d5.gno:5:2: operator << not defined on: Float64Kind diff --git a/gnovm/tests/files/types/shift_d50.gno b/gnovm/tests/files/types/shift_d50.gno new file mode 100644 index 00000000000..fec552e48d7 --- /dev/null +++ b/gnovm/tests/files/types/shift_d50.gno @@ -0,0 +1,13 @@ +package main + +import "fmt" + +func main() { + x := 11 + y := uint64(-(1.0 << 2) << x) + println(y) + fmt.Printf("%T \n", y) +} + +// Error: +// main/files/types/shift_d50.gno:7:7: bigint underflows target kind diff --git a/gnovm/tests/files/types/shift_d51.gno b/gnovm/tests/files/types/shift_d51.gno new file mode 100644 index 00000000000..bd2b432479f --- /dev/null +++ b/gnovm/tests/files/types/shift_d51.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 1.0 + a <<= 1 + println(a) +} + +// Error: +// main/files/types/shift_d51.gno:5:2: operator <<= not defined on: Float64Kind diff --git a/gnovm/tests/files/types/shift_d52.gno b/gnovm/tests/files/types/shift_d52.gno new file mode 100644 index 00000000000..f998381ef1c --- /dev/null +++ b/gnovm/tests/files/types/shift_d52.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := 1 + a <<= 1 + println(a) +} + +// Output: +// 2 diff --git a/gnovm/tests/files/types/shift_d53.gno b/gnovm/tests/files/types/shift_d53.gno new file mode 100644 index 00000000000..575dc1e146b --- /dev/null +++ b/gnovm/tests/files/types/shift_d53.gno @@ -0,0 +1,12 @@ +package main + +import "fmt" + +func main() { + a := 1 // a is inferred as int + b := a << 3 // b is also int + fmt.Printf("%T, %T, %d, %d \n", a, b, a, b) +} + +// Output: +// int, int, 1, 8 diff --git a/gnovm/tests/files/types/shift_d54.gno b/gnovm/tests/files/types/shift_d54.gno new file mode 100644 index 00000000000..13266f44379 --- /dev/null +++ b/gnovm/tests/files/types/shift_d54.gno @@ -0,0 +1,14 @@ +package main + +import "fmt" + +func main() { + a := 5 // infer type int + var b int32 = 10 + c := b + a<<2 + + fmt.Printf("%T, %d \n", c, c) +} + +// Error: +// main/files/types/shift_d54.gno:8:7: invalid operation: mismatched types int32 and int diff --git a/gnovm/tests/files/types/shift_d55.gno b/gnovm/tests/files/types/shift_d55.gno new file mode 100644 index 00000000000..58628376421 --- /dev/null +++ b/gnovm/tests/files/types/shift_d55.gno @@ -0,0 +1,16 @@ +package main + +import "fmt" + +func shiftReturn() int64 { + return 1 << 4 // The shift result is cast to int64 +} + +func main() { + r := shiftReturn() + + fmt.Printf("%T, %d \n", r, r) +} + +// Output: +// int64, 16 diff --git a/gnovm/tests/files/types/shift_d56.gno b/gnovm/tests/files/types/shift_d56.gno new file mode 100644 index 00000000000..3f734bb993e --- /dev/null +++ b/gnovm/tests/files/types/shift_d56.gno @@ -0,0 +1,16 @@ +package main + +import "fmt" + +func shiftReturn() int64 { + return 1<<4 + int(1) // The shift result is cast to int64 +} + +func main() { + r := shiftReturn() + + fmt.Printf("%T, %d \n", r, r) +} + +// Error: +// main/files/types/shift_d56.gno:6:2: cannot use int as int64 diff --git a/gnovm/tests/files/types/shift_d5a.gno b/gnovm/tests/files/types/shift_d5a.gno new file mode 100644 index 00000000000..8490c751c88 --- /dev/null +++ b/gnovm/tests/files/types/shift_d5a.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 11 + y := uint64(1.0 << x) + println(y) +} + +// Output: +// 2048 diff --git a/gnovm/tests/files/types/shift_d5b.gno b/gnovm/tests/files/types/shift_d5b.gno new file mode 100644 index 00000000000..8c04105a450 --- /dev/null +++ b/gnovm/tests/files/types/shift_d5b.gno @@ -0,0 +1,10 @@ +package main + +func main() { + x := 11 + y := float32(1.0 << x) + println(y) +} + +// Error: +// main/files/types/shift_d5b.gno:5:7: operator << not defined on: Float32Kind diff --git a/gnovm/tests/files/types/shift_d6.gno b/gnovm/tests/files/types/shift_d6.gno new file mode 100644 index 00000000000..e2ce1d02157 --- /dev/null +++ b/gnovm/tests/files/types/shift_d6.gno @@ -0,0 +1,18 @@ +package main + +import "fmt" + +func main() { + x := 11 + y := 1 << x + println(y) + fmt.Printf("%T\n", y) + fmt.Printf("%T\n", 1) + fmt.Printf("%T\n", x) +} + +// Output: +// 2048 +// int +// int +// int diff --git a/gnovm/tests/files/types/shift_d9.gno b/gnovm/tests/files/types/shift_d9.gno new file mode 100644 index 00000000000..e766e5e218d --- /dev/null +++ b/gnovm/tests/files/types/shift_d9.gno @@ -0,0 +1,9 @@ +package main + +func main() { + r := bool(1<<2+1 == 1>>2) + println(r) +} + +// Output: +// false diff --git a/gnovm/tests/files/types/shift_e0.gno b/gnovm/tests/files/types/shift_e0.gno new file mode 100644 index 00000000000..d5b75063d3e --- /dev/null +++ b/gnovm/tests/files/types/shift_e0.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(1 << -1) +} + +// Error: +// main/files/types/shift_e0.gno:4:10: invalid operation: negative shift count: (const (-1 bigint)) diff --git a/gnovm/tests/files/types/shift_e1.gno b/gnovm/tests/files/types/shift_e1.gno new file mode 100644 index 00000000000..343dee1f933 --- /dev/null +++ b/gnovm/tests/files/types/shift_e1.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(1.0 << float32(2.58485848)) +} + +// Error: +// main/files/types/shift_e1.gno:4:10: invalid operation: invalid shift count: (const (2.5848584 float32)) diff --git a/gnovm/tests/files/types/shift_e1a.gno b/gnovm/tests/files/types/shift_e1a.gno new file mode 100644 index 00000000000..bb6bedd2016 --- /dev/null +++ b/gnovm/tests/files/types/shift_e1a.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(1.0 << 2.0) +} + +// Output: +// 4 diff --git a/gnovm/tests/files/types/shift_e2.gno b/gnovm/tests/files/types/shift_e2.gno new file mode 100644 index 00000000000..192d5c1b3e9 --- /dev/null +++ b/gnovm/tests/files/types/shift_e2.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(1 << 1.25) +} + +// Error: +// main/files/types/shift_e2.gno:4:10: invalid operation: invalid shift count: (const (1.25 bigdec)) diff --git a/gnovm/tests/files/types/shift_e3.gno b/gnovm/tests/files/types/shift_e3.gno new file mode 100644 index 00000000000..81c803897c7 --- /dev/null +++ b/gnovm/tests/files/types/shift_e3.gno @@ -0,0 +1,9 @@ +package main + +func main() { + x := 1.25 + println(1 << x) +} + +// Error: +// main/files/types/shift_e3.gno:5:10: invalid operation: invalid shift count: x diff --git a/gnovm/tests/files/types/shift_e4.gno b/gnovm/tests/files/types/shift_e4.gno new file mode 100644 index 00000000000..02746eb04fe --- /dev/null +++ b/gnovm/tests/files/types/shift_e4.gno @@ -0,0 +1,9 @@ +package main + +func main() { + x := 1.25 + println(1 << x) +} + +// Error: +// main/files/types/shift_e4.gno:5:10: invalid operation: invalid shift count: x \ No newline at end of file diff --git a/gnovm/tests/files/types/shift_e5.gno b/gnovm/tests/files/types/shift_e5.gno new file mode 100644 index 00000000000..acd351bd50d --- /dev/null +++ b/gnovm/tests/files/types/shift_e5.gno @@ -0,0 +1,9 @@ +package main + +func main() { + x := -1 + println(1 << x) +} + +// Error: +// runtime error: negative shift amount: (-1 int) diff --git a/gnovm/tests/files/types/shift_e6.gno b/gnovm/tests/files/types/shift_e6.gno new file mode 100644 index 00000000000..43cb2464132 --- /dev/null +++ b/gnovm/tests/files/types/shift_e6.gno @@ -0,0 +1,9 @@ +package main + +func main() { + x := -1 + println(1 >> x) +} + +// Error: +// runtime error: negative shift amount: (-1 int) diff --git a/gnovm/tests/files/types/shift_e7.gno b/gnovm/tests/files/types/shift_e7.gno new file mode 100644 index 00000000000..c7d8aded350 --- /dev/null +++ b/gnovm/tests/files/types/shift_e7.gno @@ -0,0 +1,9 @@ +package main + +func main() { + y := 1 + y <<= -1 +} + +// Error: +// main/files/types/shift_e7.gno:5:2: invalid operation: negative shift count: (-1 bigint) diff --git a/gnovm/tests/files/types/shift_e7a.gno b/gnovm/tests/files/types/shift_e7a.gno new file mode 100644 index 00000000000..2e81fc102bc --- /dev/null +++ b/gnovm/tests/files/types/shift_e7a.gno @@ -0,0 +1,9 @@ +package main + +func main() { + a := float64(-100) + println(1 << a) +} + +// Error: +// main/files/types/shift_e7a.gno:5:10: invalid operation: invalid shift count: a diff --git a/gnovm/tests/files/types/shift_e7b.gno b/gnovm/tests/files/types/shift_e7b.gno new file mode 100644 index 00000000000..80766d2928e --- /dev/null +++ b/gnovm/tests/files/types/shift_e7b.gno @@ -0,0 +1,8 @@ +package main + +func main() { + println(1 << float64(-1)) +} + +// Error: +// main/files/types/shift_e7b.gno:4:10: invalid operation: invalid shift count: (const (-1 float64)) diff --git a/gnovm/tests/files/types/shift_e8.gno b/gnovm/tests/files/types/shift_e8.gno new file mode 100644 index 00000000000..1940dd9b8fb --- /dev/null +++ b/gnovm/tests/files/types/shift_e8.gno @@ -0,0 +1,9 @@ +package main + +func main() { + y := 1 + y <<= 1.25 +} + +// Error: +// main/files/types/shift_e8.gno:5:2: invalid operation: invalid shift count: (const (1.25 bigdec)) diff --git a/gnovm/tests/files/types/shift_e9.gno b/gnovm/tests/files/types/shift_e9.gno new file mode 100644 index 00000000000..2bd408860f2 --- /dev/null +++ b/gnovm/tests/files/types/shift_e9.gno @@ -0,0 +1,11 @@ +package main + +func main() { + x := -1 + y := 1 + y <<= x + println(y) +} + +// Error: +// runtime error: negative shift amount: (-1 int) diff --git a/gnovm/tests/files/types/shift_e9a.gno b/gnovm/tests/files/types/shift_e9a.gno new file mode 100644 index 00000000000..03ce9343948 --- /dev/null +++ b/gnovm/tests/files/types/shift_e9a.gno @@ -0,0 +1,11 @@ +package main + +func main() { + x := -1 + y := 1 + y >>= x + println(y) +} + +// Error: +// runtime error: negative shift amount: (-1 int) diff --git a/gnovm/tests/files/types/shift_f1a.gno b/gnovm/tests/files/types/shift_f1a.gno new file mode 100644 index 00000000000..ca35144bacc --- /dev/null +++ b/gnovm/tests/files/types/shift_f1a.gno @@ -0,0 +1,12 @@ +package main + +func main() { + var s uint = 33 + + var u1 bool + u1 = 1< bigint NEQ bigdec diff --git a/gnovm/tests/files/types/shift_f2e.gno b/gnovm/tests/files/types/shift_f2e.gno new file mode 100644 index 00000000000..dec0a2a6626 --- /dev/null +++ b/gnovm/tests/files/types/shift_f2e.gno @@ -0,0 +1,10 @@ +package main + +func main() { + var s uint = 33 + var u2 = 1.0< Date: Tue, 15 Oct 2024 16:26:16 +0200 Subject: [PATCH 2/7] =?UTF-8?q?chore:=20farewell=20Dylan=20=F0=9F=91=8B=20?= =?UTF-8?q?(#2951)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/CODEOWNERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 3870ff30539..8566e861db9 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -64,9 +64,9 @@ # GnoVM/Gnolang. /gnovm/ @jaekwon @moul @piux2 @thehowl /gnovm/stdlibs/ @thehowl -/gnovm/tests/ @jaekwon @deelawn @thehowl @mvertes +/gnovm/tests/ @jaekwon @thehowl @mvertes /gnovm/cmd/gno/ @moul @thehowl -/gnovm/pkg/gnolang/ @jaekwon @moul @piux2 @deelawn +/gnovm/pkg/gnolang/ @jaekwon @moul @piux2 /gnovm/pkg/doc/ @thehowl /gnovm/pkg/repl/ @mvertes @ajnavarro /gnovm/pkg/gnomod/ @thehowl From d741140c099f427e568ecd5f8ca82b983c94ac82 Mon Sep 17 00:00:00 2001 From: Malek Lahbib <111009238+MalekLahbib@users.noreply.github.com> Date: Tue, 15 Oct 2024 19:25:45 +0200 Subject: [PATCH 3/7] fix(p/demo/uassert): amend ineffective assignment (#2936)
Contributors' checklist... - [ ] Added new tests, or not needed, or not feasible - [ ] Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory - [ ] Updated the official documentation or not needed - [ ] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [ ] Added references to related issues and PRs - [ ] Provided any useful hints for running manual tests - [ ] 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).
--- examples/gno.land/p/demo/uassert/uassert.gno | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/gno.land/p/demo/uassert/uassert.gno b/examples/gno.land/p/demo/uassert/uassert.gno index 2776e93dca9..f9c0ab3efc8 100644 --- a/examples/gno.land/p/demo/uassert/uassert.gno +++ b/examples/gno.land/p/demo/uassert/uassert.gno @@ -266,7 +266,7 @@ func NotEqual(t TestingT, expected, actual interface{}, msgs ...string) bool { if av, ok := actual.(string); ok { notEqual = ev != av ok_ = true - es, as = ev, as + es, as = ev, av } case std.Address: if av, ok := actual.(std.Address); ok { From 679301ab829ee576246b03c8381bab2212baa82d Mon Sep 17 00:00:00 2001 From: Leon Hudak <33522493+leohhhn@users.noreply.github.com> Date: Tue, 15 Oct 2024 19:52:43 +0200 Subject: [PATCH 4/7] fix(r/leon/config): fix config bug (#2934) ## Description Fixes a bug in `r/leon/config`.
Contributors' checklist... - [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).
--- examples/gno.land/r/leon/config/config.gno | 20 +++++++++----------- examples/gno.land/r/leon/home/home.gno | 14 ++++++++++++-- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/examples/gno.land/r/leon/config/config.gno b/examples/gno.land/r/leon/config/config.gno index cbc1e537e3f..bc800ec8263 100644 --- a/examples/gno.land/r/leon/config/config.gno +++ b/examples/gno.land/r/leon/config/config.gno @@ -8,6 +8,9 @@ import ( var ( main std.Address // leon's main address backup std.Address // backup address + + ErrInvalidAddr = errors.New("leon's config: invalid address") + ErrUnauthorized = errors.New("leon's config: unauthorized") ) func init() { @@ -24,7 +27,7 @@ func Backup() std.Address { func SetAddress(a std.Address) error { if !a.IsValid() { - return errors.New("config: invalid address") + return ErrInvalidAddr } if err := checkAuthorized(); err != nil { @@ -37,7 +40,7 @@ func SetAddress(a std.Address) error { func SetBackup(a std.Address) error { if !a.IsValid() { - return errors.New("config: invalid address") + return ErrInvalidAddr } if err := checkAuthorized(); err != nil { @@ -50,16 +53,11 @@ func SetBackup(a std.Address) error { func checkAuthorized() error { caller := std.PrevRealm().Addr() - if caller != main || caller != backup { - return errors.New("config: unauthorized") + isAuthorized := caller == main || caller == backup + + if !isAuthorized { + return ErrUnauthorized } return nil } - -func AssertAuthorized() { - caller := std.PrevRealm().Addr() - if caller != main || caller != backup { - panic("config: unauthorized") - } -} diff --git a/examples/gno.land/r/leon/home/home.gno b/examples/gno.land/r/leon/home/home.gno index 1f6a07e8959..ba688792a4c 100644 --- a/examples/gno.land/r/leon/home/home.gno +++ b/examples/gno.land/r/leon/home/home.gno @@ -34,13 +34,19 @@ TODO import r/gh } func UpdatePFP(url, caption string) { - config.AssertAuthorized() + if !isAuthorized(std.PrevRealm().Addr()) { + panic(config.ErrUnauthorized) + } + pfp = url pfpCaption = caption } func UpdateAboutMe(col1, col2 string) { - config.AssertAuthorized() + if !isAuthorized(std.PrevRealm().Addr()) { + panic(config.ErrUnauthorized) + } + abtMe[0] = col1 abtMe[1] = col2 } @@ -119,3 +125,7 @@ func renderMillipede() string { return out } + +func isAuthorized(addr std.Address) bool { + return addr == config.Address() || addr == config.Backup() +} From a73cb22e58d8b81413c35aa0b5b4dfece2dfecd3 Mon Sep 17 00:00:00 2001 From: Marc Vertes Date: Tue, 15 Oct 2024 22:54:09 +0200 Subject: [PATCH 5/7] chore: fix issues reported by `go vet` (#2952) Passing `go vet` is the minimum level of code quality for a go project. This is addressed here for the full mono-repo. Mainly trivial changes, except for a few `copy lock` issues which could be more meaningful (kept for a separate pull request). Addresses #2954 (but not sufficient to close it yet). Hint for reviewers: it's easier to review each commit individually.
Contributors' checklist... - [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 - [ ] Added references to related issues and PRs - [x] Provided any useful hints for running manual tests - [ ] 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).
--- gno.land/pkg/gnoweb/gnoweb.go | 4 ++-- gno.land/pkg/sdk/vm/builtins.go | 4 ++-- gno.land/pkg/sdk/vm/keeper_test.go | 18 +++++++-------- gnovm/pkg/gnomod/read.go | 2 +- gnovm/tests/file.go | 4 ++-- misc/logos/cmd/logos.go | 2 +- tm2/pkg/amino/wellknown.go | 1 - tm2/pkg/bft/abci/example/kvstore/helpers.go | 2 +- .../example/kvstore/persistent_kvstore.go | 2 +- tm2/pkg/bft/consensus/state.go | 22 +++++++++---------- tm2/pkg/bft/consensus/wal_generator.go | 2 +- tm2/pkg/bft/types/params.go | 6 ++--- tm2/pkg/crypto/hd/hdpath_test.go | 4 ++-- tm2/pkg/db/boltdb/boltdb.go | 4 ++-- tm2/pkg/db/memdb/mem_db.go | 2 +- tm2/pkg/p2p/switch.go | 2 +- tm2/pkg/sdk/bank/keeper_test.go | 2 +- tm2/pkg/sdk/baseapp.go | 4 ---- tm2/pkg/sdk/baseapp_test.go | 14 ++++++------ tm2/pkg/store/cache/store_test.go | 8 +++---- tm2/pkg/store/gas/store_test.go | 8 +++---- tm2/pkg/store/iavl/store_test.go | 4 ++-- tm2/pkg/store/prefix/store_test.go | 12 +++++----- 23 files changed, 64 insertions(+), 69 deletions(-) diff --git a/gno.land/pkg/gnoweb/gnoweb.go b/gno.land/pkg/gnoweb/gnoweb.go index 5377ae6a420..3e6249cf126 100644 --- a/gno.land/pkg/gnoweb/gnoweb.go +++ b/gno.land/pkg/gnoweb/gnoweb.go @@ -476,7 +476,7 @@ func handleNotFound(logger *slog.Logger, app gotuna.App, cfg *Config, path strin // decode path for non-ascii characters decodedPath, err := url.PathUnescape(path) if err != nil { - logger.Error("failed to decode path", err) + logger.Error("failed to decode path", "error", err) decodedPath = path } w.WriteHeader(http.StatusNotFound) @@ -491,7 +491,7 @@ func writeError(logger *slog.Logger, w http.ResponseWriter, err error) { if details := errors.Unwrap(err); details != nil { logger.Error("handler", "error", err, "details", details) } else { - logger.Error("handler", "error:", err) + logger.Error("handler", "error", err) } // XXX: writeError should return an error page template. diff --git a/gno.land/pkg/sdk/vm/builtins.go b/gno.land/pkg/sdk/vm/builtins.go index de58cd3e8ae..d4d6b6032b2 100644 --- a/gno.land/pkg/sdk/vm/builtins.go +++ b/gno.land/pkg/sdk/vm/builtins.go @@ -42,7 +42,7 @@ func (bnk *SDKBanker) TotalCoin(denom string) int64 { func (bnk *SDKBanker) IssueCoin(b32addr crypto.Bech32Address, denom string, amount int64) { addr := crypto.MustAddressFromString(string(b32addr)) - _, err := bnk.vmk.bank.AddCoins(bnk.ctx, addr, std.Coins{std.Coin{denom, amount}}) + _, err := bnk.vmk.bank.AddCoins(bnk.ctx, addr, std.Coins{std.Coin{Denom: denom, Amount: amount}}) if err != nil { panic(err) } @@ -50,7 +50,7 @@ func (bnk *SDKBanker) IssueCoin(b32addr crypto.Bech32Address, denom string, amou func (bnk *SDKBanker) RemoveCoin(b32addr crypto.Bech32Address, denom string, amount int64) { addr := crypto.MustAddressFromString(string(b32addr)) - _, err := bnk.vmk.bank.SubtractCoins(bnk.ctx, addr, std.Coins{std.Coin{denom, amount}}) + _, err := bnk.vmk.bank.SubtractCoins(bnk.ctx, addr, std.Coins{std.Coin{Denom: denom, Amount: amount}}) if err != nil { panic(err) } diff --git a/gno.land/pkg/sdk/vm/keeper_test.go b/gno.land/pkg/sdk/vm/keeper_test.go index 9257da2ddaf..f6c6b87419d 100644 --- a/gno.land/pkg/sdk/vm/keeper_test.go +++ b/gno.land/pkg/sdk/vm/keeper_test.go @@ -81,7 +81,7 @@ func TestVMKeeperOrigSend1(t *testing.T) { // Create test package. files := []*std.MemFile{ - {"init.gno", ` + {Name: "init.gno", Body: ` package test import "std" @@ -126,7 +126,7 @@ func TestVMKeeperOrigSend2(t *testing.T) { // Create test package. files := []*std.MemFile{ - {"init.gno", ` + {Name: "init.gno", Body: ` package test import "std" @@ -180,7 +180,7 @@ func TestVMKeeperOrigSend3(t *testing.T) { // Create test package. files := []*std.MemFile{ - {"init.gno", ` + {Name: "init.gno", Body: ` package test import "std" @@ -224,7 +224,7 @@ func TestVMKeeperRealmSend1(t *testing.T) { // Create test package. files := []*std.MemFile{ - {"init.gno", ` + {Name: "init.gno", Body: ` package test import "std" @@ -268,7 +268,7 @@ func TestVMKeeperRealmSend2(t *testing.T) { // Create test package. files := []*std.MemFile{ - {"init.gno", ` + {Name: "init.gno", Body: ` package test import "std" @@ -312,7 +312,7 @@ func TestVMKeeperOrigCallerInit(t *testing.T) { // Create test package. files := []*std.MemFile{ - {"init.gno", ` + {Name: "init.gno", Body: ` package test import "std" @@ -363,7 +363,7 @@ func TestVMKeeperRunSimple(t *testing.T) { env.acck.SetAccount(ctx, acc) files := []*std.MemFile{ - {"script.gno", ` + {Name: "script.gno", Body: ` package main func main() { @@ -402,7 +402,7 @@ func testVMKeeperRunImportStdlibs(t *testing.T, env testEnv) { env.acck.SetAccount(ctx, acc) files := []*std.MemFile{ - {"script.gno", ` + {Name: "script.gno", Body: ` package main import "std" @@ -474,7 +474,7 @@ func TestVMKeeperReinitialize(t *testing.T) { // Create test package. files := []*std.MemFile{ - {"init.gno", ` + {Name: "init.gno", Body: ` package test func Echo(msg string) string { diff --git a/gnovm/pkg/gnomod/read.go b/gnovm/pkg/gnomod/read.go index a7a600f8826..d6d771429d3 100644 --- a/gnovm/pkg/gnomod/read.go +++ b/gnovm/pkg/gnomod/read.go @@ -249,7 +249,7 @@ func (in *input) readToken() { // Otherwise, save comment for later attachment to syntax tree. in.endToken(_EOLCOMMENT) - in.comments = append(in.comments, modfile.Comment{in.token.pos, in.token.text, suffix}) + in.comments = append(in.comments, modfile.Comment{Start: in.token.pos, Token: in.token.text, Suffix: suffix}) return } diff --git a/gnovm/tests/file.go b/gnovm/tests/file.go index f6bd789f1bf..1be2a0516f9 100644 --- a/gnovm/tests/file.go +++ b/gnovm/tests/file.go @@ -597,12 +597,12 @@ func (tb *testBanker) TotalCoin(denom string) int64 { func (tb *testBanker) IssueCoin(addr crypto.Bech32Address, denom string, amt int64) { coins, _ := tb.coinTable[addr] - sum := coins.Add(std.Coins{{denom, amt}}) + sum := coins.Add(std.Coins{{Denom: denom, Amount: amt}}) tb.coinTable[addr] = sum } func (tb *testBanker) RemoveCoin(addr crypto.Bech32Address, denom string, amt int64) { coins, _ := tb.coinTable[addr] - rest := coins.Sub(std.Coins{{denom, amt}}) + rest := coins.Sub(std.Coins{{Denom: denom, Amount: amt}}) tb.coinTable[addr] = rest } diff --git a/misc/logos/cmd/logos.go b/misc/logos/cmd/logos.go index 3a374fecba2..ddb979111fb 100644 --- a/misc/logos/cmd/logos.go +++ b/misc/logos/cmd/logos.go @@ -162,7 +162,7 @@ func makeTestPage() *logos.BufferedElemView { // make a buffered page. ts := makeTestString() style := logos.DefaultStyle() - style.Padding = logos.Padding{2, 2, 2, 2} + style.Padding = logos.Padding{Left: 2, Top: 2, Right: 2, Bottom: 2} style.Border = logos.DefaultBorder() // TODO width shouldn't matter. page := logos.NewPage(ts, 84, true, style) diff --git a/tm2/pkg/amino/wellknown.go b/tm2/pkg/amino/wellknown.go index 8c8ff79695d..9dbafcbecec 100644 --- a/tm2/pkg/amino/wellknown.go +++ b/tm2/pkg/amino/wellknown.go @@ -210,7 +210,6 @@ func isJSONWellKnownType(rt reflect.Type) (wellKnown bool) { default: return false } - return false } // Returns ok=false if nothing was done because the default behavior is fine (or if err). diff --git a/tm2/pkg/bft/abci/example/kvstore/helpers.go b/tm2/pkg/bft/abci/example/kvstore/helpers.go index b72b4da4778..c2a89fa20b3 100644 --- a/tm2/pkg/bft/abci/example/kvstore/helpers.go +++ b/tm2/pkg/bft/abci/example/kvstore/helpers.go @@ -11,7 +11,7 @@ import ( func RandVal(i int) abci.ValidatorUpdate { pubkey := ed25519.GenPrivKey().PubKey() power := random.RandUint16() + 1 - v := abci.ValidatorUpdate{pubkey.Address(), pubkey, int64(power)} + v := abci.ValidatorUpdate{Address: pubkey.Address(), PubKey: pubkey, Power: int64(power)} return v } diff --git a/tm2/pkg/bft/abci/example/kvstore/persistent_kvstore.go b/tm2/pkg/bft/abci/example/kvstore/persistent_kvstore.go index 01a8a3a8b8c..b6d096667ac 100644 --- a/tm2/pkg/bft/abci/example/kvstore/persistent_kvstore.go +++ b/tm2/pkg/bft/abci/example/kvstore/persistent_kvstore.go @@ -211,7 +211,7 @@ func (app *PersistentKVStoreApplication) execValidatorTx(tx []byte) (res abci.Re } // update - return app.updateValidator(abci.ValidatorUpdate{pubkey.Address(), pubkey, power}) + return app.updateValidator(abci.ValidatorUpdate{Address: pubkey.Address(), PubKey: pubkey, Power: power}) } // add, update, or remove a validator diff --git a/tm2/pkg/bft/consensus/state.go b/tm2/pkg/bft/consensus/state.go index 3f71dac368c..6faa40be20b 100644 --- a/tm2/pkg/bft/consensus/state.go +++ b/tm2/pkg/bft/consensus/state.go @@ -73,7 +73,7 @@ func (ti *timeoutInfo) GetHRS() cstypes.HRS { if ti == nil { return cstypes.HRS{} } else { - return cstypes.HRS{ti.Height, ti.Round, ti.Step} + return cstypes.HRS{Height: ti.Height, Round: ti.Round, Step: ti.Step} } } @@ -746,13 +746,13 @@ func (cs *ConsensusState) handleTimeout(ti timeoutInfo, rs cstypes.RoundState) { case cstypes.RoundStepNewRound: cs.enterPropose(ti.Height, 0) case cstypes.RoundStepPropose: - cs.evsw.FireEvent(cstypes.EventTimeoutPropose{cs.RoundState.GetHRS()}) + cs.evsw.FireEvent(cstypes.EventTimeoutPropose{HRS: cs.RoundState.GetHRS()}) cs.enterPrevote(ti.Height, ti.Round) case cstypes.RoundStepPrevoteWait: - cs.evsw.FireEvent(cstypes.EventTimeoutWait{cs.RoundState.GetHRS()}) + cs.evsw.FireEvent(cstypes.EventTimeoutWait{HRS: cs.RoundState.GetHRS()}) cs.enterPrecommit(ti.Height, ti.Round) case cstypes.RoundStepPrecommitWait: - cs.evsw.FireEvent(cstypes.EventTimeoutWait{cs.RoundState.GetHRS()}) + cs.evsw.FireEvent(cstypes.EventTimeoutWait{HRS: cs.RoundState.GetHRS()}) cs.enterPrecommit(ti.Height, ti.Round) cs.enterNewRound(ti.Height, ti.Round+1) default: @@ -1126,7 +1126,7 @@ func (cs *ConsensusState) enterPrecommit(height int64, round int) { } // At this point +2/3 prevoted for a particular block or nil. - cs.evsw.FireEvent(cstypes.EventPolka{cs.RoundState.GetHRS()}) + cs.evsw.FireEvent(cstypes.EventPolka{HRS: cs.RoundState.GetHRS()}) // the latest POLRound should be this round. polRound, _ := cs.Votes.POLInfo() @@ -1143,7 +1143,7 @@ func (cs *ConsensusState) enterPrecommit(height int64, round int) { cs.LockedRound = -1 cs.LockedBlock = nil cs.LockedBlockParts = nil - cs.evsw.FireEvent(cstypes.EventUnlock{cs.RoundState.GetHRS()}) + cs.evsw.FireEvent(cstypes.EventUnlock{HRS: cs.RoundState.GetHRS()}) } cs.signAddVote(types.PrecommitType, nil, types.PartSetHeader{}) return @@ -1155,7 +1155,7 @@ func (cs *ConsensusState) enterPrecommit(height int64, round int) { if cs.LockedBlock.HashesTo(blockID.Hash) { logger.Info("enterPrecommit: +2/3 prevoted locked block. Relocking") cs.LockedRound = round - cs.evsw.FireEvent(cstypes.EventRelock{cs.RoundState.GetHRS()}) + cs.evsw.FireEvent(cstypes.EventRelock{HRS: cs.RoundState.GetHRS()}) cs.signAddVote(types.PrecommitType, blockID.Hash, blockID.PartsHeader) return } @@ -1170,7 +1170,7 @@ func (cs *ConsensusState) enterPrecommit(height int64, round int) { cs.LockedRound = round cs.LockedBlock = cs.ProposalBlock cs.LockedBlockParts = cs.ProposalBlockParts - cs.evsw.FireEvent(cstypes.EventLock{cs.RoundState.GetHRS()}) + cs.evsw.FireEvent(cstypes.EventLock{HRS: cs.RoundState.GetHRS()}) cs.signAddVote(types.PrecommitType, blockID.Hash, blockID.PartsHeader) return } @@ -1186,7 +1186,7 @@ func (cs *ConsensusState) enterPrecommit(height int64, round int) { cs.ProposalBlock = nil cs.ProposalBlockParts = types.NewPartSetFromHeader(blockID.PartsHeader) } - cs.evsw.FireEvent(cstypes.EventUnlock{cs.RoundState.GetHRS()}) + cs.evsw.FireEvent(cstypes.EventUnlock{HRS: cs.RoundState.GetHRS()}) cs.signAddVote(types.PrecommitType, nil, types.PartSetHeader{}) } @@ -1591,7 +1591,7 @@ func (cs *ConsensusState) addVote(vote *types.Vote, peerID p2p.ID) (added bool, return } - cs.evsw.FireEvent(types.EventVote{vote}) + cs.evsw.FireEvent(types.EventVote{Vote: vote}) switch vote.Type { case types.PrevoteType: @@ -1620,7 +1620,7 @@ func (cs *ConsensusState) addVote(vote *types.Vote, peerID p2p.ID) (added bool, cs.LockedRound = -1 cs.LockedBlock = nil cs.LockedBlockParts = nil - cs.evsw.FireEvent(cstypes.EventUnlock{cs.RoundState.GetHRS()}) + cs.evsw.FireEvent(cstypes.EventUnlock{HRS: cs.RoundState.GetHRS()}) } // Update Valid* if we can. diff --git a/tm2/pkg/bft/consensus/wal_generator.go b/tm2/pkg/bft/consensus/wal_generator.go index fddcb4231e5..79c6e63c6a1 100644 --- a/tm2/pkg/bft/consensus/wal_generator.go +++ b/tm2/pkg/bft/consensus/wal_generator.go @@ -77,7 +77,7 @@ func (w *heightStopWAL) Write(m walm.WALMessage) error { } w.logger.Debug("WAL Write Message", "msg", m) - err := w.enc.Write(walm.TimedWALMessage{fixedTime, m}) + err := w.enc.Write(walm.TimedWALMessage{Time: fixedTime, Msg: m}) if err != nil { panic(fmt.Sprintf("failed to encode the msg %v", m)) } diff --git a/tm2/pkg/bft/types/params.go b/tm2/pkg/bft/types/params.go index 0b48da9329e..c2e8f304698 100644 --- a/tm2/pkg/bft/types/params.go +++ b/tm2/pkg/bft/types/params.go @@ -36,8 +36,8 @@ var validatorPubKeyTypeURLs = map[string]struct{}{ func DefaultConsensusParams() abci.ConsensusParams { return abci.ConsensusParams{ - DefaultBlockParams(), - DefaultValidatorParams(), + Block: DefaultBlockParams(), + Validator: DefaultValidatorParams(), } } @@ -51,7 +51,7 @@ func DefaultBlockParams() *abci.BlockParams { } func DefaultValidatorParams() *abci.ValidatorParams { - return &abci.ValidatorParams{[]string{ + return &abci.ValidatorParams{PubKeyTypeURLs: []string{ amino.GetTypeURL(ed25519.PubKeyEd25519{}), }} } diff --git a/tm2/pkg/crypto/hd/hdpath_test.go b/tm2/pkg/crypto/hd/hdpath_test.go index 31e806b2b1a..f79ee1151f7 100644 --- a/tm2/pkg/crypto/hd/hdpath_test.go +++ b/tm2/pkg/crypto/hd/hdpath_test.go @@ -17,7 +17,7 @@ func mnemonicToSeed(mnemonic string) []byte { return bip39.NewSeed(mnemonic, defaultBIP39Passphrase) } -func ExampleStringifyPathParams() { +func ExampleNewParams() { path := NewParams(44, 0, 0, false, 0) fmt.Println(path.String()) path = NewParams(44, 33, 7, true, 9) @@ -109,7 +109,7 @@ func TestParamsFromPath(t *testing.T) { } } -func ExampleSomeBIP32TestVecs() { +func ExampleDerivePrivateKeyForPath() { seed := mnemonicToSeed("barrel original fuel morning among eternal " + "filter ball stove pluck matrix mechanic") master, ch := ComputeMastersFromSeed(seed) diff --git a/tm2/pkg/db/boltdb/boltdb.go b/tm2/pkg/db/boltdb/boltdb.go index c35e3bb00e1..12aa20b8ce2 100644 --- a/tm2/pkg/db/boltdb/boltdb.go +++ b/tm2/pkg/db/boltdb/boltdb.go @@ -170,13 +170,13 @@ func (bdb *BoltDB) NewBatch() db.Batch { // It is safe to modify the contents of the argument after Set returns but not // before. func (bdb *boltDBBatch) Set(key, value []byte) { - bdb.ops = append(bdb.ops, internal.Operation{internal.OpTypeSet, key, value}) + bdb.ops = append(bdb.ops, internal.Operation{OpType: internal.OpTypeSet, Key: key, Value: value}) } // It is safe to modify the contents of the argument after Delete returns but // not before. func (bdb *boltDBBatch) Delete(key []byte) { - bdb.ops = append(bdb.ops, internal.Operation{internal.OpTypeDelete, key, nil}) + bdb.ops = append(bdb.ops, internal.Operation{OpType: internal.OpTypeDelete, Key: key}) } // NOTE: the operation is synchronous (see BoltDB for reasons) diff --git a/tm2/pkg/db/memdb/mem_db.go b/tm2/pkg/db/memdb/mem_db.go index 09b90b6be44..d39a9838cef 100644 --- a/tm2/pkg/db/memdb/mem_db.go +++ b/tm2/pkg/db/memdb/mem_db.go @@ -150,7 +150,7 @@ func (db *MemDB) NewBatch() dbm.Batch { db.mtx.Lock() defer db.mtx.Unlock() - return &internal.MemBatch{db, nil} + return &internal.MemBatch{DB: db} } // ---------------------------------------- diff --git a/tm2/pkg/p2p/switch.go b/tm2/pkg/p2p/switch.go index cecfc21f3ef..b2de68e1ae3 100644 --- a/tm2/pkg/p2p/switch.go +++ b/tm2/pkg/p2p/switch.go @@ -219,7 +219,7 @@ func (sw *Switch) OnStop() { if t, ok := sw.transport.(TransportLifecycle); ok { err := t.Close() if err != nil { - sw.Logger.Error("Error stopping transport on stop: ", err) + sw.Logger.Error("Error stopping transport on stop: ", "error", err) } } diff --git a/tm2/pkg/sdk/bank/keeper_test.go b/tm2/pkg/sdk/bank/keeper_test.go index 59b4c12689c..df2039a682c 100644 --- a/tm2/pkg/sdk/bank/keeper_test.go +++ b/tm2/pkg/sdk/bank/keeper_test.go @@ -133,7 +133,7 @@ func TestBankKeeper(t *testing.T) { // validate coins with invalid denoms or negative values cannot be sent // NOTE: We must use the Coin literal as the constructor does not allow // negative values. - err = bank.SendCoins(ctx, addr, addr2, sdk.Coins{sdk.Coin{"FOOCOIN", -5}}) + err = bank.SendCoins(ctx, addr, addr2, sdk.Coins{sdk.Coin{Denom: "FOOCOIN", Amount: -5}}) require.Error(t, err) } diff --git a/tm2/pkg/sdk/baseapp.go b/tm2/pkg/sdk/baseapp.go index 671f18cf058..3cabc9df336 100644 --- a/tm2/pkg/sdk/baseapp.go +++ b/tm2/pkg/sdk/baseapp.go @@ -392,10 +392,6 @@ func (app *BaseApp) Query(req abci.RequestQuery) (res abci.ResponseQuery) { default: return handleQueryCustom(app, path, req) } - - msg := "unknown query path " + req.Path - res.Error = ABCIError(std.ErrUnknownRequest(msg)) - return } func handleQueryApp(app *BaseApp, path []string, req abci.RequestQuery) (res abci.ResponseQuery) { diff --git a/tm2/pkg/sdk/baseapp_test.go b/tm2/pkg/sdk/baseapp_test.go index c8884533b30..08e8191170a 100644 --- a/tm2/pkg/sdk/baseapp_test.go +++ b/tm2/pkg/sdk/baseapp_test.go @@ -47,7 +47,7 @@ func newTxCounter(txInt int64, msgInts ...int64) std.Tx { msgs := make([]std.Msg, len(msgInts)) for i, msgInt := range msgInts { - msgs[i] = msgCounter{msgInt, false} + msgs[i] = msgCounter{Counter: msgInt, FailOnHandler: false} } tx := std.Tx{Msgs: msgs} @@ -120,13 +120,13 @@ func TestLoadVersion(t *testing.T) { header := &bft.Header{ChainID: "test-chain", Height: 1} app.BeginBlock(abci.RequestBeginBlock{Header: header}) res := app.Commit() - commitID1 := store.CommitID{1, res.Data} + commitID1 := store.CommitID{Version: 1, Hash: res.Data} // execute a block, collect commit ID header = &bft.Header{ChainID: "test-chain", Height: 2} app.BeginBlock(abci.RequestBeginBlock{Header: header}) res = app.Commit() - commitID2 := store.CommitID{2, res.Data} + commitID2 := store.CommitID{Version: 2, Hash: res.Data} // reload with LoadLatestVersion app = newBaseApp(name, db, pruningOpt) @@ -184,7 +184,7 @@ func TestLoadVersionInvalid(t *testing.T) { header := &bft.Header{ChainID: "test-chain", Height: 1} app.BeginBlock(abci.RequestBeginBlock{Header: header}) res := app.Commit() - commitID1 := store.CommitID{1, res.Data} + commitID1 := store.CommitID{Version: 1, Hash: res.Data} // create a new app with the stores mounted under the same cap key app = newBaseApp(name, db, pruningOpt) @@ -439,7 +439,7 @@ func setCounter(tx *Tx, counter int64) { func setFailOnHandler(tx *Tx, fail bool) { for i, msg := range tx.Msgs { - tx.Msgs[i] = msgCounter{msg.(msgCounter).Counter, fail} + tx.Msgs[i] = msgCounter{Counter: msg.(msgCounter).Counter, FailOnHandler: fail} } } @@ -676,8 +676,8 @@ func TestMultiMsgDeliverTx(t *testing.T) { // replace the second message with a msgCounter2 tx = newTxCounter(1, 3) - tx.Msgs = append(tx.Msgs, msgCounter2{0}) - tx.Msgs = append(tx.Msgs, msgCounter2{1}) + tx.Msgs = append(tx.Msgs, msgCounter2{Counter: 0}) + tx.Msgs = append(tx.Msgs, msgCounter2{Counter: 1}) txBytes, err = amino.Marshal(tx) require.NoError(t, err) res = app.DeliverTx(abci.RequestDeliverTx{Tx: txBytes}) diff --git a/tm2/pkg/store/cache/store_test.go b/tm2/pkg/store/cache/store_test.go index 4ac8cc64de9..1caf51ea52c 100644 --- a/tm2/pkg/store/cache/store_test.go +++ b/tm2/pkg/store/cache/store_test.go @@ -15,7 +15,7 @@ import ( ) func newCacheStore() types.Store { - mem := dbadapter.Store{memdb.NewMemDB()} + mem := dbadapter.Store{DB: memdb.NewMemDB()} return cache.New(mem) } @@ -25,7 +25,7 @@ func valFmt(i int) []byte { return bz(fmt.Sprintf("value%0.8d", i)) } func TestCacheStore(t *testing.T) { t.Parallel() - mem := dbadapter.Store{memdb.NewMemDB()} + mem := dbadapter.Store{DB: memdb.NewMemDB()} st := cache.New(mem) require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty") @@ -70,7 +70,7 @@ func TestCacheStore(t *testing.T) { func TestCacheStoreNoNilSet(t *testing.T) { t.Parallel() - mem := dbadapter.Store{memdb.NewMemDB()} + mem := dbadapter.Store{DB: memdb.NewMemDB()} st := cache.New(mem) require.Panics(t, func() { st.Set([]byte("key"), nil) }, "setting a nil value should panic") } @@ -78,7 +78,7 @@ func TestCacheStoreNoNilSet(t *testing.T) { func TestCacheStoreNested(t *testing.T) { t.Parallel() - mem := dbadapter.Store{memdb.NewMemDB()} + mem := dbadapter.Store{DB: memdb.NewMemDB()} st := cache.New(mem) // set. check its there on st and not on mem. diff --git a/tm2/pkg/store/gas/store_test.go b/tm2/pkg/store/gas/store_test.go index 5b8cc7c656c..52c8dbf08e8 100644 --- a/tm2/pkg/store/gas/store_test.go +++ b/tm2/pkg/store/gas/store_test.go @@ -20,7 +20,7 @@ func valFmt(i int) []byte { return bz(fmt.Sprintf("value%0.8d", i)) } func TestGasKVStoreBasic(t *testing.T) { t.Parallel() - mem := dbadapter.Store{memdb.NewMemDB()} + mem := dbadapter.Store{DB: memdb.NewMemDB()} meter := types.NewGasMeter(10000) st := gas.New(mem, meter, types.DefaultGasConfig()) require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty") @@ -34,7 +34,7 @@ func TestGasKVStoreBasic(t *testing.T) { func TestGasKVStoreIterator(t *testing.T) { t.Parallel() - mem := dbadapter.Store{memdb.NewMemDB()} + mem := dbadapter.Store{DB: memdb.NewMemDB()} meter := types.NewGasMeter(10000) st := gas.New(mem, meter, types.DefaultGasConfig()) require.Empty(t, st.Get(keyFmt(1)), "Expected `key1` to be empty") @@ -60,7 +60,7 @@ func TestGasKVStoreIterator(t *testing.T) { func TestGasKVStoreOutOfGasSet(t *testing.T) { t.Parallel() - mem := dbadapter.Store{memdb.NewMemDB()} + mem := dbadapter.Store{DB: memdb.NewMemDB()} meter := types.NewGasMeter(0) st := gas.New(mem, meter, types.DefaultGasConfig()) require.Panics(t, func() { st.Set(keyFmt(1), valFmt(1)) }, "Expected out-of-gas") @@ -69,7 +69,7 @@ func TestGasKVStoreOutOfGasSet(t *testing.T) { func TestGasKVStoreOutOfGasIterator(t *testing.T) { t.Parallel() - mem := dbadapter.Store{memdb.NewMemDB()} + mem := dbadapter.Store{DB: memdb.NewMemDB()} meter := types.NewGasMeter(20000) st := gas.New(mem, meter, types.DefaultGasConfig()) st.Set(keyFmt(1), valFmt(1)) diff --git a/tm2/pkg/store/iavl/store_test.go b/tm2/pkg/store/iavl/store_test.go index 6959e9172dc..9157394cb08 100644 --- a/tm2/pkg/store/iavl/store_test.go +++ b/tm2/pkg/store/iavl/store_test.go @@ -46,7 +46,7 @@ func newAlohaTree(t *testing.T, db dbm.DB) (*iavl.MutableTree, types.CommitID) { } hash, ver, err := tree.SaveVersion() require.Nil(t, err) - return tree, types.CommitID{ver, hash} + return tree, types.CommitID{Version: ver, Hash: hash} } func TestGetImmutable(t *testing.T) { @@ -58,7 +58,7 @@ func TestGetImmutable(t *testing.T) { require.True(t, tree.Set([]byte("hello"), []byte("adios"))) hash, ver, err := tree.SaveVersion() - cID = types.CommitID{ver, hash} + cID = types.CommitID{Version: ver, Hash: hash} require.Nil(t, err) _, err = store.GetImmutable(cID.Version + 1) diff --git a/tm2/pkg/store/prefix/store_test.go b/tm2/pkg/store/prefix/store_test.go index 701ceda17d5..d61b67462e8 100644 --- a/tm2/pkg/store/prefix/store_test.go +++ b/tm2/pkg/store/prefix/store_test.go @@ -106,7 +106,7 @@ func TestPrefixStoreNoNilSet(t *testing.T) { t.Parallel() meter := types.NewGasMeter(100000000) - mem := dbadapter.Store{memdb.NewMemDB()} + mem := dbadapter.Store{DB: memdb.NewMemDB()} gasStore := gas.New(mem, meter, types.DefaultGasConfig()) require.Panics(t, func() { gasStore.Set([]byte("key"), nil) }, "setting a nil value should panic") } @@ -115,7 +115,7 @@ func TestPrefixStoreIterate(t *testing.T) { t.Parallel() db := memdb.NewMemDB() - baseStore := dbadapter.Store{db} + baseStore := dbadapter.Store{DB: db} prefix := []byte("test") prefixStore := New(baseStore, prefix) @@ -165,7 +165,7 @@ func TestPrefixStoreIteratorEdgeCase(t *testing.T) { t.Parallel() db := memdb.NewMemDB() - baseStore := dbadapter.Store{db} + baseStore := dbadapter.Store{DB: db} // overflow in cpIncr prefix := []byte{0xAA, 0xFF, 0xFF} @@ -197,7 +197,7 @@ func TestPrefixStoreReverseIteratorEdgeCase(t *testing.T) { t.Parallel() db := memdb.NewMemDB() - baseStore := dbadapter.Store{db} + baseStore := dbadapter.Store{DB: db} // overflow in cpIncr prefix := []byte{0xAA, 0xFF, 0xFF} @@ -225,7 +225,7 @@ func TestPrefixStoreReverseIteratorEdgeCase(t *testing.T) { iter.Close() db = memdb.NewMemDB() - baseStore = dbadapter.Store{db} + baseStore = dbadapter.Store{DB: db} // underflow in cpDecr prefix = []byte{0xAA, 0x00, 0x00} @@ -256,7 +256,7 @@ func TestPrefixStoreReverseIteratorEdgeCase(t *testing.T) { func mockStoreWithStuff() types.Store { db := memdb.NewMemDB() - store := dbadapter.Store{db} + store := dbadapter.Store{DB: db} // Under "key" prefix store.Set(bz("key"), bz("value")) store.Set(bz("key1"), bz("value1")) From 5444859b159b40927f7771e20cc7386582a87332 Mon Sep 17 00:00:00 2001 From: Antonio Navarro Perez Date: Wed, 16 Oct 2024 11:46:26 +0200 Subject: [PATCH 6/7] chore: Remove checkbox with the reminder of adding more Benchmarks. (#2927) --- .github/pull_request_template.md | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index d76f68cba5d..12e07a9cde6 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -8,5 +8,4 @@ - [ ] No breaking changes were made, or a `BREAKING CHANGE: xxx` message was included in the description - [ ] Added references to related issues and PRs - [ ] Provided any useful hints for running manual tests -- [ ] 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). From 641d2fd91f03191016f74ea32a0ae9592b884896 Mon Sep 17 00:00:00 2001 From: Jeff Thompson Date: Wed, 16 Oct 2024 14:51:17 +0200 Subject: [PATCH 7/7] feat(tm2/crypto/keys): In the gnokey CLI, add command to update the password (#2700) The `Keybase` API supports a method to [change the password of a key](https://github.com/gnolang/gno/blob/8a62a28f672d3311163bee75f5e8f10ba3d4d52b/tm2/pkg/crypto/keys/keybase.go#L450). It is currently called `Update` which is confusing. This PR renames the API function to `Rotate` and adds the "rotate" command to the gnokey CLI. BREAKING CHANGE: The Keybase API function `Update` is renamed to `Rotate`. (Note: I haven't seen code using this function, so it should be minimal impact.)
Contributors' checklist... - [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
--------- Signed-off-by: Jeff Thompson Co-authored-by: Morgan --- .../cli/gnokey/working-with-key-pairs.md | 13 +++ gno.land/pkg/keyscli/root.go | 1 + tm2/pkg/crypto/keys/client/root.go | 1 + tm2/pkg/crypto/keys/client/rotate.go | 75 +++++++++++++++ tm2/pkg/crypto/keys/client/rotate_test.go | 95 +++++++++++++++++++ tm2/pkg/crypto/keys/keybase.go | 4 +- tm2/pkg/crypto/keys/keybase_test.go | 12 +-- tm2/pkg/crypto/keys/lazy_keybase.go | 4 +- tm2/pkg/crypto/keys/types.go | 2 +- 9 files changed, 196 insertions(+), 11 deletions(-) create mode 100644 tm2/pkg/crypto/keys/client/rotate.go create mode 100644 tm2/pkg/crypto/keys/client/rotate_test.go diff --git a/docs/gno-tooling/cli/gnokey/working-with-key-pairs.md b/docs/gno-tooling/cli/gnokey/working-with-key-pairs.md index ba03ca569b4..9bc29da6a18 100644 --- a/docs/gno-tooling/cli/gnokey/working-with-key-pairs.md +++ b/docs/gno-tooling/cli/gnokey/working-with-key-pairs.md @@ -38,6 +38,7 @@ gno.land keychain & client SUBCOMMANDS add adds key to the keybase delete deletes a key from the keybase + rotate rotate the password of a key in the keybase to a new password generate generates a bip39 mnemonic export exports private key armor import imports encrypted private key armor @@ -161,6 +162,18 @@ you can recover it using the key's mnemonic, or by importing it if it was export at a previous point in time. ::: + +## Rotating the password of a private key to a new password +To rotate the password of a private key from the `gnokey` keystore to a new password, we need to know the name or +address of the key to remove. +After we have this information, we can run the following command: + +```bash +gnokey rotate MyKey +``` + +After entering the current key decryption password and the new password, the password of the key will be updated in the keystore. + ## Exporting a private key Private keys stored in the `gnokey` keystore can be exported to a desired place on the user's filesystem. diff --git a/gno.land/pkg/keyscli/root.go b/gno.land/pkg/keyscli/root.go index 19513fc0de6..c910e01b82c 100644 --- a/gno.land/pkg/keyscli/root.go +++ b/gno.land/pkg/keyscli/root.go @@ -30,6 +30,7 @@ func NewRootCmd(io commands.IO, base client.BaseOptions) *commands.Command { cmd.AddSubCommands( client.NewAddCmd(cfg, io), client.NewDeleteCmd(cfg, io), + client.NewRotateCmd(cfg, io), client.NewGenerateCmd(cfg, io), client.NewExportCmd(cfg, io), client.NewImportCmd(cfg, io), diff --git a/tm2/pkg/crypto/keys/client/root.go b/tm2/pkg/crypto/keys/client/root.go index f69155ace85..8dcd9210a50 100644 --- a/tm2/pkg/crypto/keys/client/root.go +++ b/tm2/pkg/crypto/keys/client/root.go @@ -43,6 +43,7 @@ func NewRootCmdWithBaseConfig(io commands.IO, base BaseOptions) *commands.Comman NewExportCmd(cfg, io), NewImportCmd(cfg, io), NewListCmd(cfg, io), + NewRotateCmd(cfg, io), NewSignCmd(cfg, io), NewVerifyCmd(cfg, io), NewQueryCmd(cfg, io), diff --git a/tm2/pkg/crypto/keys/client/rotate.go b/tm2/pkg/crypto/keys/client/rotate.go new file mode 100644 index 00000000000..876e9f40b70 --- /dev/null +++ b/tm2/pkg/crypto/keys/client/rotate.go @@ -0,0 +1,75 @@ +package client + +import ( + "context" + "flag" + "fmt" + + "github.com/gnolang/gno/tm2/pkg/commands" + "github.com/gnolang/gno/tm2/pkg/crypto/keys" +) + +type RotateCfg struct { + RootCfg *BaseCfg + + Force bool +} + +func NewRotateCmd(rootCfg *BaseCfg, io commands.IO) *commands.Command { + cfg := &RotateCfg{ + RootCfg: rootCfg, + } + + return commands.NewCommand( + commands.Metadata{ + Name: "rotate", + ShortUsage: "rotate [flags] ", + ShortHelp: "rotate the password of a key in the keybase to a new password", + }, + cfg, + func(_ context.Context, args []string) error { + return execRotate(cfg, args, io) + }, + ) +} + +func (c *RotateCfg) RegisterFlags(fs *flag.FlagSet) { +} + +func execRotate(cfg *RotateCfg, args []string, io commands.IO) error { + if len(args) != 1 { + return flag.ErrHelp + } + + nameOrBech32 := args[0] + + kb, err := keys.NewKeyBaseFromDir(cfg.RootCfg.Home) + if err != nil { + return err + } + + oldpass, err := io.GetPassword("Enter the current password:", cfg.RootCfg.InsecurePasswordStdin) + if err != nil { + return err + } + + newpass, err := io.GetCheckPassword( + [2]string{ + "Enter the new password to encrypt your key to disk:", + "Repeat the password:", + }, + cfg.RootCfg.InsecurePasswordStdin, + ) + if err != nil { + return fmt.Errorf("unable to parse provided password, %w", err) + } + + getNewpass := func() (string, error) { return newpass, nil } + err = kb.Rotate(nameOrBech32, oldpass, getNewpass) + if err != nil { + return err + } + io.ErrPrintln("Password rotated") + + return nil +} diff --git a/tm2/pkg/crypto/keys/client/rotate_test.go b/tm2/pkg/crypto/keys/client/rotate_test.go new file mode 100644 index 00000000000..f365359d943 --- /dev/null +++ b/tm2/pkg/crypto/keys/client/rotate_test.go @@ -0,0 +1,95 @@ +package client + +import ( + "strings" + "testing" + + "github.com/gnolang/gno/tm2/pkg/commands" + "github.com/gnolang/gno/tm2/pkg/crypto/keys" + "github.com/gnolang/gno/tm2/pkg/testutils" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func Test_execRotate(t *testing.T) { + t.Parallel() + + // make new test dir + kbHome, kbCleanUp := testutils.NewTestCaseDir(t) + defer kbCleanUp() + + // initialize test options + cfg := &RotateCfg{ + RootCfg: &BaseCfg{ + BaseOptions: BaseOptions{ + Home: kbHome, + InsecurePasswordStdin: true, + }, + }, + } + + io := commands.NewTestIO() + + // Add test accounts to keybase. + kb, err := keys.NewKeyBaseFromDir(kbHome) + assert.NoError(t, err) + + keyName := "rotateApp_Key1" + p1, p2 := "1234", "foobar" + mnemonic := "equip will roof matter pink blind book anxiety banner elbow sun young" + + _, err = kb.CreateAccount(keyName, mnemonic, "", p1, 0, 0) + assert.NoError(t, err) + + { + // test: Key not found + args := []string{"blah"} + io.SetIn(strings.NewReader(p1 + "\n" + p2 + "\n" + p2 + "\n")) + err = execRotate(cfg, args, io) + require.Error(t, err) + require.Equal(t, "Key blah not found", err.Error()) + } + + { + // test: Wrong password + args := []string{keyName} + io.SetIn(strings.NewReader("blah" + "\n" + p2 + "\n" + p2 + "\n")) + err = execRotate(cfg, args, io) + require.Error(t, err) + require.Equal(t, "invalid account password", err.Error()) + } + + { + // test: New passwords don't match + args := []string{keyName} + io.SetIn(strings.NewReader(p1 + "\n" + p2 + "\n" + "blah" + "\n")) + err = execRotate(cfg, args, io) + require.Error(t, err) + require.Equal(t, "unable to parse provided password, passphrases don't match", err.Error()) + } + + { + // Rotate the password + args := []string{keyName} + io.SetIn(strings.NewReader(p1 + "\n" + p2 + "\n" + p2 + "\n")) + err = execRotate(cfg, args, io) + require.NoError(t, err) + } + + { + // test: The old password shouldn't work + args := []string{keyName} + io.SetIn(strings.NewReader(p1 + "\n" + p1 + "\n" + p1 + "\n")) + err = execRotate(cfg, args, io) + require.Error(t, err) + require.Equal(t, "invalid account password", err.Error()) + } + + { + // Updating the new password to itself should work + args := []string{keyName} + io.SetIn(strings.NewReader(p2 + "\n" + p2 + "\n" + p2 + "\n")) + err = execRotate(cfg, args, io) + require.NoError(t, err) + } +} diff --git a/tm2/pkg/crypto/keys/keybase.go b/tm2/pkg/crypto/keys/keybase.go index 2dc7d41be0b..c28fd1ef952 100644 --- a/tm2/pkg/crypto/keys/keybase.go +++ b/tm2/pkg/crypto/keys/keybase.go @@ -441,13 +441,13 @@ func (kb dbKeybase) Delete(nameOrBech32, passphrase string, skipPass bool) error return nil } -// Update changes the passphrase with which an already stored key is +// Rotate changes the passphrase with which an already stored key is // encrypted. // // oldpass must be the current passphrase used for encryption, // getNewpass is a function to get the passphrase to permanently replace // the current passphrase -func (kb dbKeybase) Update(nameOrBech32, oldpass string, getNewpass func() (string, error)) error { +func (kb dbKeybase) Rotate(nameOrBech32, oldpass string, getNewpass func() (string, error)) error { info, err := kb.GetByNameOrAddress(nameOrBech32) if err != nil { return err diff --git a/tm2/pkg/crypto/keys/keybase_test.go b/tm2/pkg/crypto/keys/keybase_test.go index 32cc8788b52..afcc1c56197 100644 --- a/tm2/pkg/crypto/keys/keybase_test.go +++ b/tm2/pkg/crypto/keys/keybase_test.go @@ -199,9 +199,9 @@ func assertPassword(t *testing.T, cstore Keybase, name, pass, badpass string) { t.Helper() getNewpass := func() (string, error) { return pass, nil } - err := cstore.Update(name, badpass, getNewpass) + err := cstore.Rotate(name, badpass, getNewpass) require.NotNil(t, err) - err = cstore.Update(name, pass, getNewpass) + err = cstore.Rotate(name, pass, getNewpass) require.Nil(t, err, "%+v", err) } @@ -280,7 +280,7 @@ func TestExportImportPubKey(t *testing.T) { require.NotNil(t, err) } -// TestAdvancedKeyManagement verifies update, import, export functionality +// TestAdvancedKeyManagement verifies rotate, import, export functionality func TestAdvancedKeyManagement(t *testing.T) { t.Parallel() @@ -297,14 +297,14 @@ func TestAdvancedKeyManagement(t *testing.T) { require.Nil(t, err, "%+v", err) assertPassword(t, cstore, n1, p1, p2) - // update password requires the existing password + // rotate password requires the existing password getNewpass := func() (string, error) { return p2, nil } - err = cstore.Update(n1, "jkkgkg", getNewpass) + err = cstore.Rotate(n1, "jkkgkg", getNewpass) require.NotNil(t, err) assertPassword(t, cstore, n1, p1, p2) // then it changes the password when correct - err = cstore.Update(n1, p1, getNewpass) + err = cstore.Rotate(n1, p1, getNewpass) require.NoError(t, err) // p2 is now the proper one! assertPassword(t, cstore, n1, p2, p1) diff --git a/tm2/pkg/crypto/keys/lazy_keybase.go b/tm2/pkg/crypto/keys/lazy_keybase.go index eb9c0f3b551..38cec501135 100644 --- a/tm2/pkg/crypto/keys/lazy_keybase.go +++ b/tm2/pkg/crypto/keys/lazy_keybase.go @@ -179,14 +179,14 @@ func (lkb lazyKeybase) CreateMulti(name string, pubkey crypto.PubKey) (info Info return NewDBKeybase(db).CreateMulti(name, pubkey) } -func (lkb lazyKeybase) Update(name, oldpass string, getNewpass func() (string, error)) error { +func (lkb lazyKeybase) Rotate(name, oldpass string, getNewpass func() (string, error)) error { db, err := db.NewDB(lkb.name, dbBackend, lkb.dir) if err != nil { return err } defer db.Close() - return NewDBKeybase(db).Update(name, oldpass, getNewpass) + return NewDBKeybase(db).Rotate(name, oldpass, getNewpass) } func (lkb lazyKeybase) Import(name string, armor string) (err error) { diff --git a/tm2/pkg/crypto/keys/types.go b/tm2/pkg/crypto/keys/types.go index c5d33023a0a..3865951168e 100644 --- a/tm2/pkg/crypto/keys/types.go +++ b/tm2/pkg/crypto/keys/types.go @@ -43,7 +43,7 @@ type Keybase interface { CreateMulti(name string, pubkey crypto.PubKey) (info Info, err error) // The following operations will *only* work on locally-stored keys - Update(name, oldpass string, getNewpass func() (string, error)) error + Rotate(name, oldpass string, getNewpass func() (string, error)) error Import(name string, armor string) (err error) ImportPrivKey(name, armor, decryptPassphrase, encryptPassphrase string) error ImportPrivKeyUnsafe(name, armor, encryptPassphrase string) error