Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 76e9447

Browse files
committedApr 16, 2024·
feat: github oracle
Co-authored-by: Miguel Victoria Villaquiran <Villaquiranm@users.noreply.github.com>
1 parent 3c661d8 commit 76e9447

File tree

8 files changed

+258
-32
lines changed

8 files changed

+258
-32
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
gnokey maketx addpkg \
2+
-deposit="1ugnot" \
3+
-gas-fee="1ugnot" \
4+
-gas-wanted="5000000" \
5+
-broadcast="true" \
6+
-remote="https://rpc.gno.land:443" \
7+
-chainid="portal-loop" \
8+
-pkgdir="." \
9+
-pkgpath="gno.land/r/mikecito/gh_test_4" \
10+
mykey2
11+
12+
gnokey maketx call \
13+
-gas-fee="1ugnot" \
14+
-gas-wanted="5000000" \
15+
-broadcast="true" \
16+
-remote="https://rpc.gno.land:443" \
17+
-chainid="portal-loop" \
18+
-pkgpath="gno.land/r/mikecito/gh_test_4" \
19+
-func="AdminSetOracleAddr" \
20+
-args="g1d46t4el0dduffs5j56t2razaeyvnmkxlduduuw" \
21+
mykey2
22+
23+
gnokey maketx call \
24+
-gas-fee="1ugnot" \
25+
-gas-wanted="5000000" \
26+
-broadcast="true" \
27+
-remote="https://rpc.gno.land:443" \
28+
-chainid="portal-loop" \
29+
-pkgpath="gno.land/r/mikecito/gh_test_4" \
30+
-func="OracleUpsertAccount" \
31+
-args="15034695" \
32+
-args="omarsy" \
33+
-args="6h057" \
34+
-args="user" \
35+
mykey2
36+
37+
gnokey query "vm/qeval" -data='gno.land/r/mikecito/gh_test_4
38+
AccountByID("15034695")' -remote="https://rpc.gno.land:443"
39+
40+
gnokey query "vm/qeval" -data='gno.land/r/mikecito/gh_test_4
41+
RenderAccount("g14mfv59k38r8k5vkevpu0lpqlqra0e9trwp3d32")' -remote="https://rpc.gno.land:443"
42+
43+
gnokey query "vm/qeval" -data='gno.land/r/mikecito/gh_test_4
44+
Render()' -remote="https://rpc.gno.land:443"

‎examples/gno.land/r/demo/teritori/gh/account.gno

+16-7
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
package gh
22

3-
import "errors"
3+
import (
4+
"errors"
5+
"std"
6+
7+
"gno.land/p/demo/avl"
8+
)
49

510
// Account represents a GitHub user account or organization.
611
type Account struct {
7-
id string
12+
id string
813
login string
9-
name string
10-
kind string
14+
name string
15+
kind string
1116
}
1217

1318
func (a Account) ID() string { return a.id }
@@ -23,11 +28,11 @@ func (a Account) Validate() error {
2328
if a.id == "" {
2429
return errors.New("empty id")
2530
}
26-
31+
2732
if a.login == "" {
2833
return errors.New("empty login")
2934
}
30-
if a.kind == "" {
35+
if a.kind == "" || (a.kind != UserAccount && a.kind != OrgAccount) {
3136
return errors.New("empty kind")
3237
}
3338
if a.name == "" {
@@ -37,6 +42,10 @@ func (a Account) Validate() error {
3742
return nil
3843
}
3944

45+
func (a Account) Render() string {
46+
return `{ "id": "` + a.id + `", "login": "` + a.login + `", "name": "` + a.name + `", "kind": "` + a.kind + `" }`
47+
}
48+
4049
func (a Account) String() string {
4150
// XXX: better idea?
4251
return a.URL()
@@ -54,4 +63,4 @@ func AccountByID(id string) *Account {
5463
}
5564

5665
return res.(*Account)
57-
}
66+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package gh
2+
3+
import (
4+
"std"
5+
)
6+
7+
var(
8+
adminAddr std.Address = "g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq"
9+
)
10+
11+
12+
func assertIsAdmin() {
13+
if std.GetOrigCaller() != adminAddr {
14+
panic("restricted area")
15+
}
16+
}
17+
18+
func setAdminAddress(address std.Address) {
19+
adminAddr = address
20+
}
21+
22+
func SetAdminAddress(address std.Address) {
23+
assertIsAdmin()
24+
setAdminAddress(address)
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package gh
2+
3+
import (
4+
"std"
5+
"testing"
6+
7+
"gno.land/p/demo/avl"
8+
"gno.land/p/demo/testutils"
9+
)
10+
11+
func TestAssertIsAdmin(t *testing.T) {
12+
adminAddr = "g1test1234"
13+
randomuser := testutils.TestAddress("g1unknown_player")
14+
defer func() {
15+
if r := recover(); r != nil {
16+
}
17+
}()
18+
std.TestSetOrigCaller(randomuser)
19+
assertIsAdmin()
20+
t.Fatalf("should fail because not admin")
21+
}
22+

‎examples/gno.land/r/demo/teritori/gh/oracle.gno

+6-14
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,14 @@ import (
99
)
1010

1111
var (
12-
accounts avl.Tree // uri -> Account
13-
lastUpdateTime time.Time // used by the bot to only upload the diff
14-
oracleAddr std.Address = "g1eunnckcl6r8ncwj0lrpxu9g5062xcvwxqlrf29"
15-
adminAddr std.Address = "g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq"
12+
accounts avl.Tree // id -> Account
13+
lastUpdateTime time.Time // used by the bot to only upload the diff
14+
oracleAddr std.Address
1615
)
1716

1817
func OracleLastUpdated() time.Time { return lastUpdateTime }
1918

20-
func OracleUpsertAccount(id, name, kind string) {
19+
func OracleUpsertAccount(id, login, name, kind string) {
2120
assertIsOracle()
2221
lastUpdateTime = time.Now()
2322

@@ -33,6 +32,7 @@ func OracleUpsertAccount(id, name, kind string) {
3332
// update fields
3433
account.name = name
3534
account.kind = kind
35+
account.login = login
3636

3737
if err := account.Validate(); err != nil {
3838
panic(err)
@@ -47,16 +47,8 @@ func AdminSetOracleAddr(new std.Address) {
4747
oracleAddr = new
4848
}
4949

50-
func AdminGetOracleAddr() std.Address { return oracleAddr }
51-
52-
func assertIsAdmin() {
53-
if std.GetOrigCaller() != adminAddr {
54-
panic("restricted area")
55-
}
56-
}
57-
5850
func assertIsOracle() {
5951
if std.GetOrigCaller() != oracleAddr {
6052
panic("restricted area")
6153
}
62-
}
54+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package gh
2+
3+
import (
4+
"std"
5+
"testing"
6+
"time"
7+
8+
"gno.land/p/demo/avl"
9+
"gno.land/p/demo/testutils"
10+
)
11+
12+
func TestOracleUpsertUserIsNotOracle(t *testing.T) {
13+
oracleAddr = "g1test1234"
14+
var randomuser = "g1unknown_player"
15+
user := testutils.TestAddress("user")
16+
defer func() {
17+
if r := recover(); r != nil {
18+
}
19+
}()
20+
OracleUpsertAccount("acountID", "villaquiranm","john doe","user")
21+
t.Fatalf("should fail because not admin")
22+
}
23+
24+
func TestOracleUpsertUserOk(t *testing.T) {
25+
oracleAddr = "g1random"
26+
if accounts.Size() != 0 {
27+
t.Fatalf("Accounts is not empty")
28+
}
29+
now := time.Now()
30+
31+
std.TestSetOrigCaller(oracleAddr)
32+
33+
var randomuser = "g1unknown_player"
34+
OracleUpsertAccount("acountID", "villaquiranm","john doe","user")
35+
36+
if accounts.Size() != 1 {
37+
t.Fatalf("User was not created")
38+
}
39+
40+
OracleUpsertAccount("acountID", "villaquiranm","john doe","user")
41+
42+
if accounts.Size() != 1 {
43+
t.Fatalf("User was created more than once")
44+
}
45+
46+
if OracleLastUpdated().Unix() < now.Unix() {
47+
t.Fatalf("OracleLastUpdated was not changed")
48+
}
49+
}
50+
51+
func TestAssertIsOracle(t *testing.T) {
52+
std.TestSetOrigCaller(adminAddr)
53+
AdminSetOracleAddr("g1random123")
54+
defer func() {
55+
if r := recover(); r != nil {
56+
}
57+
}()
58+
assertIsOracle()
59+
t.Fatalf("should fail because user is not oracle")
60+
}
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,63 @@
11
package gh
2+
3+
import (
4+
"std"
5+
6+
"gno.land/p/demo/avl"
7+
)
8+
29
var (
3-
addressesToAccount avl.Tree // address -> AccountLink
4-
adminAddr std.Address = "g1u7y667z64x2h7vc6fmpcprgey4ck233jaww9zq"
5-
)
6-
func LinkAccount(accountID string, address std.Address) {
10+
addressToAccount avl.Tree // address -> Account
11+
guardian std.Address // guardian address
12+
)
13+
14+
func init() {
15+
addressToAccount = avl.Tree{}
16+
setAdminAddress(std.GetOrigCaller())
17+
}
18+
19+
// Todo maybe we should gave multi guardian
20+
func SetGuardian(address std.Address) {
721
assertIsAdmin()
8-
account := AccountByID(id string)
22+
guardian = address
23+
}
24+
25+
func LinkAccount(accountID string, address std.Address, signature string) {
26+
verifySignature(accountID+" "+address.String(), signature)
27+
28+
account := AccountByID(accountID)
929
if account == nil {
1030
panic("account not found")
1131
}
12-
13-
addressesToAccount.Set(address, account)
32+
33+
addressToAccount.Set(address.String(), account)
1434
}
1535

16-
func assertIsAdmin() {
17-
if std.GetOrigCaller() != adminAddr {
18-
panic("restricted area")
36+
func RenderAccount(address std.Address) string {
37+
account, ok := addressToAccount.Get(address.String())
38+
if !ok {
39+
panic("account not found")
40+
}
41+
42+
return account.(*Account).Render()
43+
}
44+
45+
func Render(address string) string {
46+
if address != "" {
47+
return RenderAccount(std.Address(address))
1948
}
20-
}
49+
str := "["
50+
addressToAccount.Iterate("", "", func(key string, value interface{}) bool {
51+
account := value.(*Account)
52+
str += account.Render()
53+
str += ","
54+
return false
55+
})
56+
str += "]"
57+
58+
return str
59+
}
60+
61+
func verifySignature(message, signature string) bool {
62+
return true
63+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package gh
2+
3+
import (
4+
"std"
5+
"testing"
6+
7+
"gno.land/p/demo/avl"
8+
"gno.land/p/demo/testutils"
9+
)
10+
11+
func TestLinkAccount(t *testing.T) {
12+
adminAddr = "g1test1234"
13+
14+
user := testutils.TestAddress("user")
15+
admin := testutils.TestAddress("admin")
16+
17+
std.TestSetOrigCaller(admin)
18+
setAdminAddress(admin)
19+
AdminSetOracleAddr(admin)
20+
21+
OracleUpsertAccount("123","user", "user", UserAccount)
22+
LinkAccount("123", user, "signature")
23+
accountInPublic, ok := addressToAccount.Get(user.String())
24+
if !ok {
25+
t.Fatalf("account not found")
26+
}
27+
account := AccountByID("123")
28+
if accountInPublic != account {
29+
t.Fatalf("account is not same")
30+
}
31+
}

0 commit comments

Comments
 (0)
Please sign in to comment.