diff --git a/x/logic/predicate/address.go b/x/logic/predicate/address.go index e0dc837f..dcc1a0af 100644 --- a/x/logic/predicate/address.go +++ b/x/logic/predicate/address.go @@ -13,7 +13,6 @@ func Bech32Address(vm *engine.VM, hrp, address, bech32 engine.Term, cont engine. return engine.Delay(func(ctx context.Context) *engine.Promise { switch b := env.Resolve(bech32).(type) { case engine.Variable: - return nil case engine.Atom: h, a, err := bech322.DecodeAndConvert(b.String()) if err != nil { @@ -23,5 +22,30 @@ func Bech32Address(vm *engine.VM, hrp, address, bech32 engine.Term, cont engine. default: return engine.Error(fmt.Errorf("bech32_address/3: invalid data type: %T, should be Atom or Variable", b)) } + + switch a := env.Resolve(address).(type) { + case engine.Compound: + if a.Arity() != 2 || a.Functor().String() != "." { + return engine.Error(fmt.Errorf("bech32_address/3: Address should be a List of bytes, give %T", a)) + } + + iter := engine.ListIterator{List: a, Env: env} + data, err := ListToBytes(iter, env) + if err != nil { + return engine.Error(fmt.Errorf("bech32_address/3: failed convert term to bytes list: %w", err)) + } + h, ok := env.Resolve(hrp).(engine.Atom) + if !ok { + return engine.Error(fmt.Errorf("bech32_address/3: Hrp should be instantiated in Address convertion context")) + } + b, err := bech322.ConvertAndEncode(h.String(), data) + if err != nil { + return engine.Error(fmt.Errorf("bech32_address/3: failed convert base64 encoded address to bech32 string encoded: %w", err)) + } + + return engine.Unify(vm, bech32, util.StringToTerm(b), cont, env) + } + + return engine.Error(fmt.Errorf("bech32_address/3: Address should be a List of bytes when bech32 string encoded value is given")) }) } diff --git a/x/logic/predicate/address_test.go b/x/logic/predicate/address_test.go index d6b7d866..2895a690 100644 --- a/x/logic/predicate/address_test.go +++ b/x/logic/predicate/address_test.go @@ -43,6 +43,13 @@ func TestBech32(t *testing.T) { query: `bech32_address('okp5', Address, 'okp415wn30a9z4uc692s0kkx5fp5d4qfr3ac7sj9dqn').`, wantSuccess: false, }, + { + query: `bech32_address('okp4', [163,167,23,244,162,175,49,162,170,15,181,141,68,134,141,168,18,56,247,30], Bech32).`, + wantResult: []types.TermResults{{ + "Bech32": "okp415wn30a9z4uc692s0kkx5fp5d4qfr3ac7sj9dqn", + }}, + wantSuccess: true, + }, } for nc, tc := range cases { Convey(fmt.Sprintf("Given the query #%d: %s", nc, tc.query), func() {