Skip to content

Commit

Permalink
feat(logic): reigster eddsa_verify/4 predicate
Browse files Browse the repository at this point in the history
  • Loading branch information
bdeneux authored and ccamel committed Oct 27, 2023
1 parent a92ec86 commit 2a19e91
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 1 deletion.
1 change: 1 addition & 0 deletions x/logic/interpreter/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ var registry = map[string]any{
"json_prolog/2": predicate.JSONProlog,
"uri_encoded/3": predicate.URIEncoded,
"read_string/3": predicate.ReadString,
"eddsa_verify/4": predicate.EDDSAVerify,
}

// RegistryNames is the list of the predicate names in the Registry.
Expand Down
29 changes: 28 additions & 1 deletion x/logic/predicate/crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"encoding/hex"
"fmt"

cometcrypto "github.com/cometbft/cometbft/crypto"
"github.com/cometbft/cometbft/crypto/secp256k1"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256r1"
"github.com/ichiban/prolog/engine"
Expand Down Expand Up @@ -37,7 +38,7 @@ func SHAHash(vm *engine.VM, data, hash engine.Term, cont engine.Cont, env *engin
var result []byte
switch d := env.Resolve(data).(type) {
case engine.Atom:
result = crypto.Sha256([]byte(d.String()))
result = cometcrypto.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))
Expand Down Expand Up @@ -108,6 +109,32 @@ const (
Ed25519 Alg = "ed25519"
)

func EDDSAVerify(vm *engine.VM, key, data, sig, options engine.Term, cont engine.Cont, env *engine.Env) *engine.Promise {
return engine.Delay(func(ctx context.Context) *engine.Promise {
pubKey, err := TermToBytes(key, env)
if err != nil {
return engine.Error(fmt.Errorf("eddsa_verify/4: decoding public key: %w", err))
}

msg, err := TermToBytes(data, env)
if err != nil {
return engine.Error(fmt.Errorf("eddsa_verify/4: decoding data: %w", err))
}

signature, err := TermToBytes(sig, env)
if err != nil {
return engine.Error(fmt.Errorf("eddsa_verify/4: decoding signature: %w", err))
}

// TODO: Create function hasDecoding option
r, err := verifySignature(Ed25519, pubKey, msg, signature)
if err != nil {
return engine.Error(fmt.Errorf("eddsa_verify/4: failed verify signature: %w", err))
}
return engine.Bool(r)
})
}

func verifySignature(alg Alg, pubKey crypto.PublicKey, msg, sig []byte) (bool, error) {
switch alg {
case Ed25519:
Expand Down
14 changes: 14 additions & 0 deletions x/logic/predicate/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,20 @@ func BytesToList(bt []byte) engine.Term {
return engine.List(terms...)
}

func TermToBytes(term engine.Term, env *engine.Env) ([]byte, error) {
switch b := env.Resolve(term).(type) {
case engine.Compound:
if b.Arity() != 2 || b.Functor().String() != "." {
return nil, fmt.Errorf("term should be a List, give %T", b)
}
iter := engine.ListIterator{List: b, Env: env}

return ListToBytes(iter, env)
default:
return nil, fmt.Errorf("invalid term type: %T, should be Atom or List", term)
}
}

func ListToBytes(terms engine.ListIterator, env *engine.Env) ([]byte, error) {
bt := make([]byte, 0)
for terms.Next() {
Expand Down

0 comments on commit 2a19e91

Please sign in to comment.