From 5c70aba06fbccf0ac73893ae41a883e62d23f248 Mon Sep 17 00:00:00 2001 From: Benjamin DENEUX Date: Thu, 16 Feb 2023 16:45:35 +0100 Subject: [PATCH 1/8] feat(logic): add crypto_hash/2 predicate --- x/logic/interpreter/registry.go | 1 + x/logic/predicate/crypto.go | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 x/logic/predicate/crypto.go diff --git a/x/logic/interpreter/registry.go b/x/logic/interpreter/registry.go index 920688cb..42eb70a9 100644 --- a/x/logic/interpreter/registry.go +++ b/x/logic/interpreter/registry.go @@ -115,6 +115,7 @@ var Registry = map[string]RegistryEntry{ "bank_spendable_balances/2": {predicate.BankSpendableBalances, 1}, "bank_locked_balances/2": {predicate.BankLockedBalances, 1}, "did_components/2": {predicate.DIDComponents, 1}, + "crypto_hash/2": {predicate.CryptoHash, 1}, } // RegistryNames is the list of the predicate names in the Registry. diff --git a/x/logic/predicate/crypto.go b/x/logic/predicate/crypto.go new file mode 100644 index 00000000..fd61ecb5 --- /dev/null +++ b/x/logic/predicate/crypto.go @@ -0,0 +1,22 @@ +package predicate + +import ( + "context" + "encoding/hex" + "fmt" + + "github.com/ichiban/prolog/engine" + "github.com/tendermint/tendermint/crypto" +) + +func CryptoHash(vm *engine.VM, data, hash engine.Term, cont engine.Cont, env *engine.Env) *engine.Promise { + return engine.Delay(func(ctx context.Context) *engine.Promise { + switch d := env.Resolve(data).(type) { + case engine.Atom: + result := crypto.Sha256([]byte(d.String())) + return engine.Unify(vm, hash, engine.NewAtom(hex.EncodeToString(result)), cont, env) + default: + return engine.Error(fmt.Errorf("crypto_hash/2: cannot unify %s from %s", data, hash)) + } + }) +} From 0ba365a74fbb47911eff386c93c3787ab9435dfc Mon Sep 17 00:00:00 2001 From: Benjamin DENEUX Date: Fri, 17 Feb 2023 09:29:53 +0100 Subject: [PATCH 2/8] test(logic): add crypto_hash/2 tests --- x/logic/predicate/crypto.go | 15 ++++-- x/logic/predicate/crypto_test.go | 92 ++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+), 5 deletions(-) create mode 100644 x/logic/predicate/crypto_test.go diff --git a/x/logic/predicate/crypto.go b/x/logic/predicate/crypto.go index fd61ecb5..d711681a 100644 --- a/x/logic/predicate/crypto.go +++ b/x/logic/predicate/crypto.go @@ -11,12 +11,17 @@ import ( func CryptoHash(vm *engine.VM, data, hash engine.Term, cont engine.Cont, env *engine.Env) *engine.Promise { return engine.Delay(func(ctx context.Context) *engine.Promise { - switch d := env.Resolve(data).(type) { - case engine.Atom: - result := crypto.Sha256([]byte(d.String())) - return engine.Unify(vm, hash, engine.NewAtom(hex.EncodeToString(result)), cont, env) + switch h := env.Resolve(hash).(type) { + case engine.Variable: + switch d := env.Resolve(data).(type) { + case engine.Atom: + result := crypto.Sha256([]byte(d.String())) + return engine.Unify(vm, hash, engine.NewAtom(hex.EncodeToString(result)), cont, env) + default: + return engine.Error(fmt.Errorf("crypto_hash/2: invalid data type: %T, should be Atom", d)) + } default: - return engine.Error(fmt.Errorf("crypto_hash/2: cannot unify %s from %s", data, hash)) + return engine.Error(fmt.Errorf("crypto_hash/2: invalid hash type: %T, should be Variable", h)) } }) } diff --git a/x/logic/predicate/crypto_test.go b/x/logic/predicate/crypto_test.go new file mode 100644 index 00000000..31a327d1 --- /dev/null +++ b/x/logic/predicate/crypto_test.go @@ -0,0 +1,92 @@ +//nolint:gocognit +package predicate + +import ( + "fmt" + "testing" + + "github.com/cosmos/cosmos-sdk/store" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/ichiban/prolog/engine" + "github.com/okp4/okp4d/x/logic/testutil" + "github.com/okp4/okp4d/x/logic/types" + . "github.com/smartystreets/goconvey/convey" + "github.com/tendermint/tendermint/libs/log" + tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + tmdb "github.com/tendermint/tm-db" +) + +func TestCryptoHash(t *testing.T) { + Convey("Given a test cases", t, func() { + cases := []struct { + program string + query string + wantResult []types.TermResults + wantError error + }{ + { + query: `crypto_hash('foo', Hash).`, + wantResult: []types.TermResults{{"Hash": "'2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae'"}}, + }, + { + query: `crypto_hash(Foo, Hash).`, + wantResult: []types.TermResults{}, + wantError: fmt.Errorf("crypto_hash/2: invalid data type: engine.Variable, should be Atom"), + }, + { + query: `crypto_hash(foo, bar).`, + wantResult: []types.TermResults{}, + wantError: fmt.Errorf("crypto_hash/2: invalid hash type: engine.Atom, should be Variable"), + }, + } + for nc, tc := range cases { + Convey(fmt.Sprintf("Given the query #%d: %s", nc, tc.query), func() { + Convey("and a context", func() { + db := tmdb.NewMemDB() + stateStore := store.NewCommitMultiStore(db) + ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger()) + + Convey("and a vm", func() { + interpreter := testutil.NewInterpreterMust(ctx) + interpreter.Register2(engine.NewAtom("crypto_hash"), CryptoHash) + + err := interpreter.Compile(ctx, tc.program) + So(err, ShouldBeNil) + + Convey("When the predicate is called", func() { + sols, err := interpreter.QueryContext(ctx, tc.query) + + Convey("Then the error should be nil", func() { + So(err, ShouldBeNil) + So(sols, ShouldNotBeNil) + + Convey("and the bindings should be as expected", func() { + var got []types.TermResults + for sols.Next() { + m := types.TermResults{} + err := sols.Scan(m) + So(err, ShouldBeNil) + + got = append(got, m) + } + if tc.wantError != nil { + So(sols.Err(), ShouldNotBeNil) + So(sols.Err().Error(), ShouldEqual, tc.wantError.Error()) + } else { + So(sols.Err(), ShouldBeNil) + So(len(got), ShouldEqual, len(tc.wantResult)) + for iGot, resultGot := range got { + for varGot, termGot := range resultGot { + So(testutil.ReindexUnknownVariables(termGot), ShouldEqual, tc.wantResult[iGot][varGot]) + } + } + } + }) + }) + }) + }) + }) + }) + } + }) +} From 6534b9b5afc1a6f40680b159b149d4d4fc6f149c Mon Sep 17 00:00:00 2001 From: Benjamin DENEUX Date: Fri, 17 Feb 2023 11:28:52 +0100 Subject: [PATCH 3/8] feat(logic): return List of byte for crypto_hash/2 --- x/logic/predicate/crypto.go | 3 +-- x/logic/predicate/crypto_test.go | 2 +- x/logic/predicate/util.go | 8 ++++++++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/x/logic/predicate/crypto.go b/x/logic/predicate/crypto.go index d711681a..6b140c02 100644 --- a/x/logic/predicate/crypto.go +++ b/x/logic/predicate/crypto.go @@ -2,7 +2,6 @@ package predicate import ( "context" - "encoding/hex" "fmt" "github.com/ichiban/prolog/engine" @@ -16,7 +15,7 @@ func CryptoHash(vm *engine.VM, data, hash engine.Term, cont engine.Cont, env *en switch d := env.Resolve(data).(type) { case engine.Atom: result := crypto.Sha256([]byte(d.String())) - return engine.Unify(vm, hash, engine.NewAtom(hex.EncodeToString(result)), cont, env) + return engine.Unify(vm, hash, BytesToList(result), cont, env) default: return engine.Error(fmt.Errorf("crypto_hash/2: invalid data type: %T, should be Atom", d)) } diff --git a/x/logic/predicate/crypto_test.go b/x/logic/predicate/crypto_test.go index 31a327d1..7eb0ff92 100644 --- a/x/logic/predicate/crypto_test.go +++ b/x/logic/predicate/crypto_test.go @@ -26,7 +26,7 @@ func TestCryptoHash(t *testing.T) { }{ { query: `crypto_hash('foo', Hash).`, - wantResult: []types.TermResults{{"Hash": "'2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae'"}}, + wantResult: []types.TermResults{{"Hash": "[44,38,180,107,104,255,198,143,249,155,69,60,29,48,65,52,19,66,45,112,100,131,191,160,249,138,94,136,98,102,231,174]"}}, }, { query: `crypto_hash(Foo, Hash).`, diff --git a/x/logic/predicate/util.go b/x/logic/predicate/util.go index fb6c33da..9b4fb4ab 100644 --- a/x/logic/predicate/util.go +++ b/x/logic/predicate/util.go @@ -52,3 +52,11 @@ func CoinsToTerm(coins sdk.Coins) engine.Term { func Tuple(args ...engine.Term) engine.Term { return engine.Atom(0).Apply(args...) } + +func BytesToList(bt []byte) engine.Term { + terms := make([]engine.Term, 0, len(bt)) + for _, b := range bt { + terms = append(terms, engine.Integer(b)) + } + return engine.List(terms...) +} From f55b9b0c091b4fcb891314c44966581e31f1f5ff Mon Sep 17 00:00:00 2001 From: Benjamin DENEUX Date: Fri, 17 Feb 2023 15:57:14 +0100 Subject: [PATCH 4/8] refactor(logic): rename crypto_hash/2 to sha_hash/2 --- x/logic/interpreter/registry.go | 2 +- x/logic/predicate/crypto.go | 6 +++--- x/logic/predicate/crypto_test.go | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/x/logic/interpreter/registry.go b/x/logic/interpreter/registry.go index 42eb70a9..e3e1bb06 100644 --- a/x/logic/interpreter/registry.go +++ b/x/logic/interpreter/registry.go @@ -115,7 +115,7 @@ var Registry = map[string]RegistryEntry{ "bank_spendable_balances/2": {predicate.BankSpendableBalances, 1}, "bank_locked_balances/2": {predicate.BankLockedBalances, 1}, "did_components/2": {predicate.DIDComponents, 1}, - "crypto_hash/2": {predicate.CryptoHash, 1}, + "sha_hash/2": {predicate.SHAHash, 1}, } // RegistryNames is the list of the predicate names in the Registry. diff --git a/x/logic/predicate/crypto.go b/x/logic/predicate/crypto.go index 6b140c02..18f36d3e 100644 --- a/x/logic/predicate/crypto.go +++ b/x/logic/predicate/crypto.go @@ -8,7 +8,7 @@ import ( "github.com/tendermint/tendermint/crypto" ) -func CryptoHash(vm *engine.VM, data, hash engine.Term, cont engine.Cont, env *engine.Env) *engine.Promise { +func SHAHash(vm *engine.VM, data, hash engine.Term, cont engine.Cont, env *engine.Env) *engine.Promise { return engine.Delay(func(ctx context.Context) *engine.Promise { switch h := env.Resolve(hash).(type) { case engine.Variable: @@ -17,10 +17,10 @@ func CryptoHash(vm *engine.VM, data, hash engine.Term, cont engine.Cont, env *en result := crypto.Sha256([]byte(d.String())) return engine.Unify(vm, hash, BytesToList(result), cont, env) default: - return engine.Error(fmt.Errorf("crypto_hash/2: invalid data type: %T, should be Atom", d)) + return engine.Error(fmt.Errorf("sha_hash/2: invalid data type: %T, should be Atom", d)) } default: - return engine.Error(fmt.Errorf("crypto_hash/2: invalid hash type: %T, should be Variable", h)) + return engine.Error(fmt.Errorf("sha_hash/2: invalid hash type: %T, should be Variable", h)) } }) } diff --git a/x/logic/predicate/crypto_test.go b/x/logic/predicate/crypto_test.go index 7eb0ff92..54335d9b 100644 --- a/x/logic/predicate/crypto_test.go +++ b/x/logic/predicate/crypto_test.go @@ -25,18 +25,18 @@ func TestCryptoHash(t *testing.T) { wantError error }{ { - query: `crypto_hash('foo', Hash).`, + query: `sha_hash('foo', Hash).`, wantResult: []types.TermResults{{"Hash": "[44,38,180,107,104,255,198,143,249,155,69,60,29,48,65,52,19,66,45,112,100,131,191,160,249,138,94,136,98,102,231,174]"}}, }, { - query: `crypto_hash(Foo, Hash).`, + query: `sha_hash(Foo, Hash).`, wantResult: []types.TermResults{}, - wantError: fmt.Errorf("crypto_hash/2: invalid data type: engine.Variable, should be Atom"), + wantError: fmt.Errorf("sha_hash/2: invalid data type: engine.Variable, should be Atom"), }, { - query: `crypto_hash(foo, bar).`, + query: `sha_hash(foo, bar).`, wantResult: []types.TermResults{}, - wantError: fmt.Errorf("crypto_hash/2: invalid hash type: engine.Atom, should be Variable"), + wantError: fmt.Errorf("sha_hash/2: invalid hash type: engine.Atom, should be Variable"), }, } for nc, tc := range cases { @@ -48,7 +48,7 @@ func TestCryptoHash(t *testing.T) { Convey("and a vm", func() { interpreter := testutil.NewInterpreterMust(ctx) - interpreter.Register2(engine.NewAtom("crypto_hash"), CryptoHash) + interpreter.Register2(engine.NewAtom("sha_hash"), SHAHash) err := interpreter.Compile(ctx, tc.program) So(err, ShouldBeNil) From da067ba67f8508c61eea404aa08dd1f474cc4386 Mon Sep 17 00:00:00 2001 From: Benjamin DENEUX Date: Mon, 20 Feb 2023 14:26:33 +0100 Subject: [PATCH 5/8] test(logic): add more sha_hash/2 tests --- x/logic/predicate/crypto.go | 16 ++++----- x/logic/predicate/crypto_test.go | 60 +++++++++++++++++++++++--------- x/logic/predicate/util.go | 19 ++++++++++ 3 files changed, 69 insertions(+), 26 deletions(-) diff --git a/x/logic/predicate/crypto.go b/x/logic/predicate/crypto.go index 18f36d3e..ae6e0522 100644 --- a/x/logic/predicate/crypto.go +++ b/x/logic/predicate/crypto.go @@ -10,17 +10,13 @@ import ( func SHAHash(vm *engine.VM, data, hash engine.Term, cont engine.Cont, env *engine.Env) *engine.Promise { return engine.Delay(func(ctx context.Context) *engine.Promise { - switch h := env.Resolve(hash).(type) { - case engine.Variable: - switch d := env.Resolve(data).(type) { - case engine.Atom: - result := crypto.Sha256([]byte(d.String())) - return engine.Unify(vm, hash, BytesToList(result), cont, env) - default: - return engine.Error(fmt.Errorf("sha_hash/2: invalid data type: %T, should be Atom", d)) - } + var result []byte + switch d := env.Resolve(data).(type) { + case engine.Atom: + result = crypto.Sha256([]byte(d.String())) + return engine.Unify(vm, hash, BytesToList(result), cont, env) default: - return engine.Error(fmt.Errorf("sha_hash/2: invalid hash type: %T, should be Variable", h)) + return engine.Error(fmt.Errorf("sha_hash/2: invalid data type: %T, should be Atom", d)) } }) } diff --git a/x/logic/predicate/crypto_test.go b/x/logic/predicate/crypto_test.go index 54335d9b..4bd6ad2f 100644 --- a/x/logic/predicate/crypto_test.go +++ b/x/logic/predicate/crypto_test.go @@ -19,24 +19,46 @@ import ( func TestCryptoHash(t *testing.T) { Convey("Given a test cases", t, func() { cases := []struct { - program string - query string - wantResult []types.TermResults - wantError error + program string + query string + wantResult []types.TermResults + wantError error + wantSuccess bool }{ { - query: `sha_hash('foo', Hash).`, - wantResult: []types.TermResults{{"Hash": "[44,38,180,107,104,255,198,143,249,155,69,60,29,48,65,52,19,66,45,112,100,131,191,160,249,138,94,136,98,102,231,174]"}}, + query: `sha_hash('foo', Hash).`, + wantResult: []types.TermResults{{"Hash": "[44,38,180,107,104,255,198,143,249,155,69,60,29,48,65,52,19,66,45,112,100,131,191,160,249,138,94,136,98,102,231,174]"}}, + wantSuccess: true, }, { - query: `sha_hash(Foo, Hash).`, - wantResult: []types.TermResults{}, - wantError: fmt.Errorf("sha_hash/2: invalid data type: engine.Variable, should be Atom"), + query: `sha_hash(Foo, Hash).`, + wantResult: []types.TermResults{}, + wantError: fmt.Errorf("sha_hash/2: invalid data type: engine.Variable, should be Atom"), + wantSuccess: false, }, { - query: `sha_hash(foo, bar).`, - wantResult: []types.TermResults{}, - wantError: fmt.Errorf("sha_hash/2: invalid hash type: engine.Atom, should be Variable"), + query: `sha_hash('bar', [44,38,180,107,104,255,198,143,249,155,69,60,29,48,65,52,19,66,45,112,100,131,191,160,249,138,94,136,98,102,231,174]).`, + wantSuccess: false, + }, + { + query: `sha_hash('bar', [252,222,43,46,219,165,107,244,8,96,31,183,33,254,155,92,51,141,16,238,66,158,160,79,174,85,17,182,143,191,143,185]).`, + wantResult: []types.TermResults{{}}, + wantSuccess: true, + }, + { + query: `sha_hash('bar', [345,222,43,46,219,165,107,244,8,96,31,183,33,254,155,92,51,141,16,238,66,158,160,79,174,85,17,182,143,191,143,185]).`, + wantSuccess: false, + }, + { + program: `test :- sha_hash('bar', H), H == [252,222,43,46,219,165,107,244,8,96,31,183,33,254,155,92,51,141,16,238,66,158,160,79,174,85,17,182,143,191,143,185].`, + query: `test.`, + wantResult: []types.TermResults{{}}, + wantSuccess: true, + }, + { + program: `test :- sha_hash('bar', H), H == [2252,222,43,46,219,165,107,244,8,96,31,183,33,254,155,92,51,141,16,238,66,158,160,79,174,85,17,182,143,191,143,185].`, + query: `test.`, + wantSuccess: false, }, } for nc, tc := range cases { @@ -74,11 +96,17 @@ func TestCryptoHash(t *testing.T) { So(sols.Err().Error(), ShouldEqual, tc.wantError.Error()) } else { So(sols.Err(), ShouldBeNil) - So(len(got), ShouldEqual, len(tc.wantResult)) - for iGot, resultGot := range got { - for varGot, termGot := range resultGot { - So(testutil.ReindexUnknownVariables(termGot), ShouldEqual, tc.wantResult[iGot][varGot]) + + if tc.wantSuccess { + So(len(got), ShouldBeGreaterThan, 0) + So(len(got), ShouldEqual, len(tc.wantResult)) + for iGot, resultGot := range got { + for varGot, termGot := range resultGot { + So(testutil.ReindexUnknownVariables(termGot), ShouldEqual, tc.wantResult[iGot][varGot]) + } } + } else { + So(len(got), ShouldEqual, 0) } } }) diff --git a/x/logic/predicate/util.go b/x/logic/predicate/util.go index 9b4fb4ab..4e29b985 100644 --- a/x/logic/predicate/util.go +++ b/x/logic/predicate/util.go @@ -1,6 +1,7 @@ package predicate import ( + "fmt" "sort" sdk "github.com/cosmos/cosmos-sdk/types" @@ -60,3 +61,21 @@ func BytesToList(bt []byte) engine.Term { } return engine.List(terms...) } + +func ListToBytes(terms engine.ListIterator, env *engine.Env) ([]byte, error) { + bt := make([]byte, 0) + for terms.Next() { + term := env.Resolve(terms.Current()) + switch t := term.(type) { + case engine.Integer: + //b, ok := + //if !ok { + // return nil, fmt.Errorf("couldn't cast '%d' to byte", term) + //} + bt = append(bt, byte(t)) + default: + return nil, fmt.Errorf("invalid term type in list %T, only integer allowed", term) + } + } + return bt, nil +} From eb167ee688e0200a4449ba1d76ce7f7a041242d5 Mon Sep 17 00:00:00 2001 From: Benjamin DENEUX Date: Mon, 20 Feb 2023 16:06:15 +0100 Subject: [PATCH 6/8] feat(logic): add hex_bytes/2 predicate --- x/logic/interpreter/registry.go | 1 + x/logic/predicate/crypto.go | 44 +++++++++++++++++++++++++++++++++ x/logic/predicate/util.go | 4 --- 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/x/logic/interpreter/registry.go b/x/logic/interpreter/registry.go index e3e1bb06..6dfefb64 100644 --- a/x/logic/interpreter/registry.go +++ b/x/logic/interpreter/registry.go @@ -116,6 +116,7 @@ var Registry = map[string]RegistryEntry{ "bank_locked_balances/2": {predicate.BankLockedBalances, 1}, "did_components/2": {predicate.DIDComponents, 1}, "sha_hash/2": {predicate.SHAHash, 1}, + "hex_bytes/2": {predicate.HexBytes, 1}, } // RegistryNames is the list of the predicate names in the Registry. diff --git a/x/logic/predicate/crypto.go b/x/logic/predicate/crypto.go index ae6e0522..2a448c18 100644 --- a/x/logic/predicate/crypto.go +++ b/x/logic/predicate/crypto.go @@ -2,9 +2,11 @@ package predicate import ( "context" + "encoding/hex" "fmt" "github.com/ichiban/prolog/engine" + "github.com/okp4/okp4d/x/logic/util" "github.com/tendermint/tendermint/crypto" ) @@ -20,3 +22,45 @@ func SHAHash(vm *engine.VM, data, hash engine.Term, cont engine.Cont, env *engin } }) } + +func HexBytes(vm *engine.VM, hexa, bts engine.Term, cont engine.Cont, env *engine.Env) *engine.Promise { + return engine.Delay(func(ctx context.Context) *engine.Promise { + var result []byte + + switch h := env.Resolve(hexa).(type) { + case engine.Variable: + case engine.Atom: + src := []byte(h.String()) + result = make([]byte, hex.DecodedLen(len(src))) + _, err := hex.Decode(result, src) + if err != nil { + return engine.Error(fmt.Errorf("hex_bytes/2: failed decode hexadecimal %w", err)) + } + default: + return engine.Error(fmt.Errorf("hex_bytes/2: invalid hex type: %T, should be Atom or Variable", h)) + } + + switch b := env.Resolve(bts).(type) { + case engine.Variable: + if result == nil { + return engine.Error(fmt.Errorf("hex_bytes/2: nil hexadecimal conversion in input")) + } + return engine.Unify(vm, bts, BytesToList(result), cont, env) + case engine.Compound: + if b.Arity() != 2 || b.Functor().String() != "." { + return engine.Error(fmt.Errorf("hex_bytes/2: bytes should be a List, give %T", b)) + } + iter := engine.ListIterator{List: b, Env: env} + + src, err := ListToBytes(iter, env) + if err != nil { + return engine.Error(fmt.Errorf("hex_bytes/2: failed convert list into bytes: %w", err)) + } + dst := hex.EncodeToString(src) + return engine.Unify(vm, hexa, util.StringToTerm(dst), cont, env) + default: + return engine.Error(fmt.Errorf("hex_bytes/2: invalid hex type: %T, should be Variable or List", b)) + } + + }) +} diff --git a/x/logic/predicate/util.go b/x/logic/predicate/util.go index 4e29b985..eaab5591 100644 --- a/x/logic/predicate/util.go +++ b/x/logic/predicate/util.go @@ -68,10 +68,6 @@ func ListToBytes(terms engine.ListIterator, env *engine.Env) ([]byte, error) { term := env.Resolve(terms.Current()) switch t := term.(type) { case engine.Integer: - //b, ok := - //if !ok { - // return nil, fmt.Errorf("couldn't cast '%d' to byte", term) - //} bt = append(bt, byte(t)) default: return nil, fmt.Errorf("invalid term type in list %T, only integer allowed", term) From 8dd70dc441eecdbd566bcb9993e7eb5eefebb8a8 Mon Sep 17 00:00:00 2001 From: Benjamin DENEUX Date: Mon, 20 Feb 2023 16:06:32 +0100 Subject: [PATCH 7/8] test(logic): add test for hex_bytes/2 predicate --- x/logic/predicate/crypto_test.go | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/x/logic/predicate/crypto_test.go b/x/logic/predicate/crypto_test.go index 4bd6ad2f..76aed660 100644 --- a/x/logic/predicate/crypto_test.go +++ b/x/logic/predicate/crypto_test.go @@ -60,6 +60,34 @@ func TestCryptoHash(t *testing.T) { query: `test.`, wantSuccess: false, }, + { + query: `hex_bytes(Hex, [44,38,180,107,104,255,198,143,249,155,69,60,29,48,65,52,19,66,45,112,100,131,191,160,249,138,94,136,98,102,231,174]).`, + wantResult: []types.TermResults{{"Hex": "'2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae'"}}, + wantSuccess: true, + }, + { + query: `hex_bytes('2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae', Bytes).`, + wantResult: []types.TermResults{{"Bytes": "[44,38,180,107,104,255,198,143,249,155,69,60,29,48,65,52,19,66,45,112,100,131,191,160,249,138,94,136,98,102,231,174]"}}, + wantSuccess: true, + }, + { + query: `hex_bytes('2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae', [44,38,180,107,104,255,198,143,249,155,69,60,29,48,65,52,19,66,45,112,100,131,191,160,249,138,94,136,98,102,231,174]).`, + wantResult: []types.TermResults{{}}, + wantSuccess: true, + }, + { + query: `hex_bytes('3c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae', [44,38,180,107,104,255,198,143,249,155,69,60,29,48,65,52,19,66,45,112,100,131,191,160,249,138,94,136,98,102,231,174]).`, + wantSuccess: false, + }, + { + query: `hex_bytes('fail', [44,38,180,107,104,255,198,143,249,155,69,60,29,48,65,52,19,66,45,112,100,131,191,160,249,138,94,136,98,102,231,174]).`, + wantError: fmt.Errorf("hex_bytes/2: failed decode hexadecimal encoding/hex: invalid byte: U+0069 'i'"), + wantSuccess: false, + }, + { + query: `hex_bytes('2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae', [345,38,180,107,104,255,198,143,249,155,69,60,29,48,65,52,19,66,45,112,100,131,191,160,249,138,94,136,98,102,231,174]).`, + wantSuccess: false, + }, } for nc, tc := range cases { Convey(fmt.Sprintf("Given the query #%d: %s", nc, tc.query), func() { @@ -71,6 +99,7 @@ func TestCryptoHash(t *testing.T) { Convey("and a vm", func() { interpreter := testutil.NewInterpreterMust(ctx) interpreter.Register2(engine.NewAtom("sha_hash"), SHAHash) + interpreter.Register2(engine.NewAtom("hex_bytes"), HexBytes) err := interpreter.Compile(ctx, tc.program) So(err, ShouldBeNil) From 1ac14dd826858dd9e777d82a1830c65a10da18cc Mon Sep 17 00:00:00 2001 From: Benjamin DENEUX Date: Tue, 21 Feb 2023 08:41:21 +0100 Subject: [PATCH 8/8] fix(logic): linter and unit tests --- x/logic/predicate/crypto.go | 1 - x/logic/predicate/crypto_test.go | 50 ++++++++++++++++++++++---------- 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/x/logic/predicate/crypto.go b/x/logic/predicate/crypto.go index 2a448c18..4a519104 100644 --- a/x/logic/predicate/crypto.go +++ b/x/logic/predicate/crypto.go @@ -61,6 +61,5 @@ func HexBytes(vm *engine.VM, hexa, bts engine.Term, cont engine.Cont, env *engin default: return engine.Error(fmt.Errorf("hex_bytes/2: invalid hex type: %T, should be Variable or List", b)) } - }) } diff --git a/x/logic/predicate/crypto_test.go b/x/logic/predicate/crypto_test.go index 76aed660..4a94c6a8 100644 --- a/x/logic/predicate/crypto_test.go +++ b/x/logic/predicate/crypto_test.go @@ -1,4 +1,4 @@ -//nolint:gocognit +//nolint:gocognit,lll package predicate import ( @@ -26,8 +26,10 @@ func TestCryptoHash(t *testing.T) { wantSuccess bool }{ { - query: `sha_hash('foo', Hash).`, - wantResult: []types.TermResults{{"Hash": "[44,38,180,107,104,255,198,143,249,155,69,60,29,48,65,52,19,66,45,112,100,131,191,160,249,138,94,136,98,102,231,174]"}}, + query: `sha_hash('foo', Hash).`, + wantResult: []types.TermResults{{ + "Hash": "[44,38,180,107,104,255,198,143,249,155,69,60,29,48,65,52,19,66,45,112,100,131,191,160,249,138,94,136,98,102,231,174]", + }}, wantSuccess: true, }, { @@ -37,57 +39,75 @@ func TestCryptoHash(t *testing.T) { wantSuccess: false, }, { - query: `sha_hash('bar', [44,38,180,107,104,255,198,143,249,155,69,60,29,48,65,52,19,66,45,112,100,131,191,160,249,138,94,136,98,102,231,174]).`, + query: `sha_hash('bar', +[44,38,180,107,104,255,198,143,249,155,69,60,29,48,65,52,19,66,45,112,100,131,191,160,249,138,94,136,98,102,231,174]).`, wantSuccess: false, }, { - query: `sha_hash('bar', [252,222,43,46,219,165,107,244,8,96,31,183,33,254,155,92,51,141,16,238,66,158,160,79,174,85,17,182,143,191,143,185]).`, + query: `sha_hash('bar', +[252,222,43,46,219,165,107,244,8,96,31,183,33,254,155,92,51,141,16,238,66,158,160,79,174,85,17,182,143,191,143,185]).`, wantResult: []types.TermResults{{}}, wantSuccess: true, }, { - query: `sha_hash('bar', [345,222,43,46,219,165,107,244,8,96,31,183,33,254,155,92,51,141,16,238,66,158,160,79,174,85,17,182,143,191,143,185]).`, + query: `sha_hash('bar', +[345,222,43,46,219,165,107,244,8,96,31,183,33,254,155,92,51,141,16,238,66,158,160,79,174,85,17,182,143,191,143,185]).`, wantSuccess: false, }, { - program: `test :- sha_hash('bar', H), H == [252,222,43,46,219,165,107,244,8,96,31,183,33,254,155,92,51,141,16,238,66,158,160,79,174,85,17,182,143,191,143,185].`, + program: `test :- sha_hash('bar', H), +H == [252,222,43,46,219,165,107,244,8,96,31,183,33,254,155,92,51,141,16,238,66,158,160,79,174,85,17,182,143,191,143,185].`, query: `test.`, wantResult: []types.TermResults{{}}, wantSuccess: true, }, { - program: `test :- sha_hash('bar', H), H == [2252,222,43,46,219,165,107,244,8,96,31,183,33,254,155,92,51,141,16,238,66,158,160,79,174,85,17,182,143,191,143,185].`, + program: `test :- sha_hash('bar', H), +H == [2252,222,43,46,219,165,107,244,8,96,31,183,33,254,155,92,51,141,16,238,66,158,160,79,174,85,17,182,143,191,143,185].`, query: `test.`, wantSuccess: false, }, { - query: `hex_bytes(Hex, [44,38,180,107,104,255,198,143,249,155,69,60,29,48,65,52,19,66,45,112,100,131,191,160,249,138,94,136,98,102,231,174]).`, + query: `hex_bytes(Hex, +[44,38,180,107,104,255,198,143,249,155,69,60,29,48,65,52,19,66,45,112,100,131,191,160,249,138,94,136,98,102,231,174]).`, wantResult: []types.TermResults{{"Hex": "'2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae'"}}, wantSuccess: true, }, { - query: `hex_bytes('2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae', Bytes).`, - wantResult: []types.TermResults{{"Bytes": "[44,38,180,107,104,255,198,143,249,155,69,60,29,48,65,52,19,66,45,112,100,131,191,160,249,138,94,136,98,102,231,174]"}}, + query: `hex_bytes('2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae', Bytes).`, + wantResult: []types.TermResults{{ + "Bytes": "[44,38,180,107,104,255,198,143,249,155,69,60,29,48,65,52,19,66,45,112,100,131,191,160,249,138,94,136,98,102,231,174]", + }}, wantSuccess: true, }, { - query: `hex_bytes('2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae', [44,38,180,107,104,255,198,143,249,155,69,60,29,48,65,52,19,66,45,112,100,131,191,160,249,138,94,136,98,102,231,174]).`, + query: `hex_bytes('2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae', +[44,38,180,107,104,255,198,143,249,155,69,60,29,48,65,52,19,66,45,112,100,131,191,160,249,138,94,136,98,102,231,174]).`, wantResult: []types.TermResults{{}}, wantSuccess: true, }, { - query: `hex_bytes('3c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae', [44,38,180,107,104,255,198,143,249,155,69,60,29,48,65,52,19,66,45,112,100,131,191,160,249,138,94,136,98,102,231,174]).`, + query: `hex_bytes('3c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae', +[44,38,180,107,104,255,198,143,249,155,69,60,29,48,65,52,19,66,45,112,100,131,191,160,249,138,94,136,98,102,231,174]).`, wantSuccess: false, }, { - query: `hex_bytes('fail', [44,38,180,107,104,255,198,143,249,155,69,60,29,48,65,52,19,66,45,112,100,131,191,160,249,138,94,136,98,102,231,174]).`, + query: `hex_bytes('fail', +[44,38,180,107,104,255,198,143,249,155,69,60,29,48,65,52,19,66,45,112,100,131,191,160,249,138,94,136,98,102,231,174]).`, wantError: fmt.Errorf("hex_bytes/2: failed decode hexadecimal encoding/hex: invalid byte: U+0069 'i'"), wantSuccess: false, }, { - query: `hex_bytes('2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae', [345,38,180,107,104,255,198,143,249,155,69,60,29,48,65,52,19,66,45,112,100,131,191,160,249,138,94,136,98,102,231,174]).`, + query: `hex_bytes('2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae', +[345,38,180,107,104,255,198,143,249,155,69,60,29,48,65,52,19,66,45,112,100,131,191,160,249,138,94,136,98,102,231,174]).`, wantSuccess: false, }, + { + query: `hex_bytes('2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae', +[345,38,'hey',107,104,255,198,143,249,155,69,60,29,48,65,52,19,66,45,112,100,131,191,160,249,138,94,136,98,102,231,174]).`, + wantSuccess: false, + wantError: fmt.Errorf("hex_bytes/2: failed convert list into bytes: invalid term type in list engine.Atom, only integer allowed"), + }, } for nc, tc := range cases { Convey(fmt.Sprintf("Given the query #%d: %s", nc, tc.query), func() {