Skip to content

Commit

Permalink
Change gnorkle code
Browse files Browse the repository at this point in the history
  • Loading branch information
Villaquiranm committed Sep 9, 2024
1 parent 5d3987a commit a068551
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 7 deletions.
35 changes: 35 additions & 0 deletions examples/gno.land/p/demo/gnorkle/gnorkle/instance.gno
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,30 @@ func (i *Instance) HandleMessage(msg string, postHandler PostMessageHandler) (st
switch funcType {
case message.FuncTypeRequest:
return i.GetFeedDefinitions(caller)
case message.FuncTypeRelay:
publicKey, signature, relayedMsg := message.ParseRelayedMessage(msg)
i.assertSignatureIsValid(publicKey, signature, relayedMsg)

funcType, relayedMsg := message.ParseFunc(relayedMsg)

id, relayedMsg := message.ParseID(relayedMsg)
if err := assertValidID(id); err != nil {
return "", err
}

feedWithWhitelist, err := i.getFeedWithWhitelist(id)
if err != nil {
return "", err
}


if err := feedWithWhitelist.Ingest(funcType, relayedMsg, caller); err != nil {
return "", err
}

if postHandler != nil {
postHandler.Handle(i, funcType, feedWithWhitelist)
}
default:
id, msg := message.ParseID(msg)
if err := assertValidID(id); err != nil {
Expand Down Expand Up @@ -237,3 +260,15 @@ func (i *Instance) GetFeedDefinitions(forAddress string) (string, error) {
buf.WriteString("]")
return buf.String(), nil
}

func (i *Instance) assertSignatureIsValid(publicKey, signature, msg string,) {
validSignature, signer := std.VerifySignature(publicKey, signature, msg)
if !validSignature {
panic("invalid signature")
}

// For the moment just accept general whitelisted addressed not feed specific ones
if !addressIsWhitelisted(&i.whitelist, nil, signer, nil) {
panic("address is not whitelisted")
}
}
10 changes: 10 additions & 0 deletions examples/gno.land/p/demo/gnorkle/message/parse.gno
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,13 @@ func parseFirstToken(rawMsg string) (string, string) {

return msgParts[0], msgParts[1]
}

// ParseRelayedMessage parses a relayed message and returns:
// the signing public key
// the signature (commonly hexadecimal)
// The relayed message (Containing the messageFunction != Relay)
func ParseRelayedMessage(rawMsg string) ( string, string, string) {
publicKey, remainder := parseFirstToken(rawMsg)
signature, remainder := parseFirstToken(remainder)
return publicKey, signature, remainder
}
3 changes: 3 additions & 0 deletions examples/gno.land/p/demo/gnorkle/message/type.gno
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,7 @@ const (
// FuncTypeRequest means the agent is requesting feed definitions for all those
// that it is whitelisted to provide data for.
FuncTypeRequest FuncType = "request"
// FuncTypeRelay means a non whitelisted-user is relaying a message from a whitelisted agent
// the relayer user should provide a publicKey, the message to handle and a valid signature
FuncTypeRelay FuncType = "relay"
)
8 changes: 7 additions & 1 deletion gnovm/stdlibs/generated.go
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,7 @@ var nativeFuncs = [...]NativeFunc{
},
[]gno.FieldTypeExpr{
{Name: gno.N("r0"), Type: gno.X("bool")},
{Name: gno.N("r1"), Type: gno.X("string")},
},
false,
func(m *gno.Machine) {
Expand All @@ -748,13 +749,18 @@ var nativeFuncs = [...]NativeFunc{
gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 1, "")).TV, rp1)
gno.Gno2GoValue(b.GetPointerTo(nil, gno.NewValuePathBlock(1, 2, "")).TV, rp2)

r0 := libs_std.X_verifySignature(p0, p1, p2)
r0, r1 := libs_std.X_verifySignature(p0, p1, p2)

m.PushValue(gno.Go2GnoValue(
m.Alloc,
m.Store,
reflect.ValueOf(&r0).Elem(),
))
m.PushValue(gno.Go2GnoValue(
m.Alloc,
m.Store,
reflect.ValueOf(&r1).Elem(),
))
},
},
{
Expand Down
4 changes: 2 additions & 2 deletions gnovm/stdlibs/std/native.gno
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func DecodeBech32(addr Address) (prefix string, bz [20]byte, ok bool) {
return decodeBech32(string(addr))
}

func VerifySignature(pubKeySigner string,msg string, signature string) bool {
func VerifySignature(pubKeySigner string, signature string, msg string) (bool,string) {
return verifySignature(pubKeySigner, msg, signature)
}

Expand All @@ -69,4 +69,4 @@ func getRealm(height int) (address string, pkgPath string)
func derivePkgAddr(pkgPath string) string
func encodeBech32(prefix string, bz [20]byte) string
func decodeBech32(addr string) (prefix string, bz [20]byte, ok bool)
func verifySignature(pubKeySigner string,msg string, signature string) bool
func verifySignature(pubKeySigner string,msg string, signature string) (bool,string)
14 changes: 12 additions & 2 deletions gnovm/stdlibs/std/native.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package std

import (
"encoding/hex"

gno "github.com/gnolang/gno/gnovm/pkg/gnolang"
"github.com/gnolang/gno/tm2/pkg/bech32"
"github.com/gnolang/gno/tm2/pkg/crypto"
Expand Down Expand Up @@ -150,12 +152,20 @@ func X_encodeBech32(prefix string, bytes [20]byte) string {
return b32
}

func X_verifySignature(pubKeySigner string, msg string, signature string) bool {
func X_verifySignature(pubKeySigner string, msg string, signature string) (bool, string) {
key, err := crypto.PubKeyFromBech32(pubKeySigner)
if err != nil {
panic(err) // should not happen
}
return key.VerifyBytes([]byte(msg), []byte(signature))

decodedData, err := hex.DecodeString(signature)
if err != nil {
panic(err) // should not happen
}

validSignature := key.VerifyBytes([]byte(msg), decodedData)

return validSignature, key.Address().String()
}

func X_decodeBech32(addr string) (prefix string, bytes [20]byte, ok bool) {
Expand Down
10 changes: 8 additions & 2 deletions gnovm/stdlibs/std/native_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,12 +208,18 @@ func TestVerify(t *testing.T) {
maliciousMessage := "Malicious Message"
signature, _, err := kb.Sign("user", pass, []byte(goodMessage))
assert.NoError(t, err)
signatureValid, signer := X_verifySignature(publicKey, goodMessage, string(signature))

if !X_verifySignature(publicKey, goodMessage, string(signature)) {
if !signatureValid {
t.Error("verify failed")
}

if X_verifySignature(publicKey, maliciousMessage, string(signature)) {
if signer != info.GetAddress().String() {
t.Error("signer is not equal to address")
}

signatureValid, _ = X_verifySignature(publicKey, maliciousMessage, string(signature))
if signatureValid {
t.Error("verify worked on malicious message")
}
}

0 comments on commit a068551

Please sign in to comment.