diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index cca20386f7725b2676e8096f145ff48c01d3276b..4420887e10eb7359e0d377d22ca9253cdbeb2aa3 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -92,98 +92,98 @@ }, { "ImportPath": "github.com/tendermint/tendermint/account", - "Comment": "0.1-61-g64bf8ec", - "Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b" + "Comment": "0.1-63-gb0c1ee2", + "Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d" }, { "ImportPath": "github.com/tendermint/tendermint/alert", - "Comment": "0.1-61-g64bf8ec", - "Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b" + "Comment": "0.1-63-gb0c1ee2", + "Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d" }, { "ImportPath": "github.com/tendermint/tendermint/blockchain", - "Comment": "0.1-61-g64bf8ec", - "Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b" + "Comment": "0.1-63-gb0c1ee2", + "Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d" }, { "ImportPath": "github.com/tendermint/tendermint/common", - "Comment": "0.1-61-g64bf8ec", - "Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b" + "Comment": "0.1-63-gb0c1ee2", + "Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d" }, { "ImportPath": "github.com/tendermint/tendermint/config", - "Comment": "0.1-61-g64bf8ec", - "Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b" + "Comment": "0.1-63-gb0c1ee2", + "Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d" }, { "ImportPath": "github.com/tendermint/tendermint/consensus", - "Comment": "0.1-61-g64bf8ec", - "Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b" + "Comment": "0.1-63-gb0c1ee2", + "Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d" }, { "ImportPath": "github.com/tendermint/tendermint/db", - "Comment": "0.1-61-g64bf8ec", - "Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b" + "Comment": "0.1-63-gb0c1ee2", + "Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d" }, { "ImportPath": "github.com/tendermint/tendermint/events", - "Comment": "0.1-61-g64bf8ec", - "Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b" + "Comment": "0.1-63-gb0c1ee2", + "Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d" }, { "ImportPath": "github.com/tendermint/tendermint/logger", - "Comment": "0.1-61-g64bf8ec", - "Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b" + "Comment": "0.1-63-gb0c1ee2", + "Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d" }, { "ImportPath": "github.com/tendermint/tendermint/mempool", - "Comment": "0.1-61-g64bf8ec", - "Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b" + "Comment": "0.1-63-gb0c1ee2", + "Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d" }, { "ImportPath": "github.com/tendermint/tendermint/merkle", - "Comment": "0.1-61-g64bf8ec", - "Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b" + "Comment": "0.1-63-gb0c1ee2", + "Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d" }, { "ImportPath": "github.com/tendermint/tendermint/node", - "Comment": "0.1-61-g64bf8ec", - "Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b" + "Comment": "0.1-63-gb0c1ee2", + "Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d" }, { "ImportPath": "github.com/tendermint/tendermint/p2p", - "Comment": "0.1-61-g64bf8ec", - "Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b" + "Comment": "0.1-63-gb0c1ee2", + "Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d" }, { "ImportPath": "github.com/tendermint/tendermint/permission/types", - "Comment": "0.1-61-g64bf8ec", - "Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b" + "Comment": "0.1-63-gb0c1ee2", + "Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d" }, { "ImportPath": "github.com/tendermint/tendermint/rpc", - "Comment": "0.1-61-g64bf8ec", - "Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b" + "Comment": "0.1-63-gb0c1ee2", + "Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d" }, { "ImportPath": "github.com/tendermint/tendermint/state", - "Comment": "0.1-61-g64bf8ec", - "Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b" + "Comment": "0.1-63-gb0c1ee2", + "Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d" }, { "ImportPath": "github.com/tendermint/tendermint/types", - "Comment": "0.1-61-g64bf8ec", - "Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b" + "Comment": "0.1-63-gb0c1ee2", + "Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d" }, { "ImportPath": "github.com/tendermint/tendermint/vm", - "Comment": "0.1-61-g64bf8ec", - "Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b" + "Comment": "0.1-63-gb0c1ee2", + "Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d" }, { "ImportPath": "github.com/tendermint/tendermint/wire", - "Comment": "0.1-61-g64bf8ec", - "Rev": "64bf8ec7a5c48327d4d0d12e74582806ffd1906b" + "Comment": "0.1-63-gb0c1ee2", + "Rev": "b0c1ee2c3ad851cf4e7b9dc95c2e65559e5d447d" }, { "ImportPath": "github.com/tommy351/gin-cors", diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/node/node.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/node/node.go index d35c5d8491c779418bcf5e74b1dcc6ca47816d60..7c50d8425882fed2ce634a966b02f87fa7d62aa6 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/node/node.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/node/node.go @@ -70,14 +70,14 @@ func NewNode(privValidator *types.PrivValidator) *Node { wire.WriteJSON(genDoc, buf, n, err) stateDB.Set(stypes.GenDocKey, buf.Bytes()) if *err != nil { - Exit(Fmt("Unable to write gendoc to db: %v", err)) + Exit(Fmt("Unable to write gendoc to db: %v", *err)) } } else { genDocBytes := stateDB.Get(stypes.GenDocKey) err := new(error) wire.ReadJSONPtr(&genDoc, genDocBytes, err) if *err != nil { - Exit(Fmt("Unable to read gendoc from db: %v", err)) + Exit(Fmt("Unable to read gendoc from db: %v", *err)) } } // add the chainid to the global config diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/permissions_test.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/permissions_test.go index fcaf48d95a2c16cf10a2087bf7d2a543a5b15b08..580a3cc023d1451f9d23b92a38c3044cf8bbf6df 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/state/permissions_test.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/state/permissions_test.go @@ -2,6 +2,7 @@ package state import ( "bytes" + "encoding/hex" "fmt" "strconv" "testing" @@ -14,6 +15,7 @@ import ( ptypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types" . "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/state/types" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types" + vm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/vm" ) /* @@ -868,9 +870,9 @@ func TestSNativeCALL(t *testing.T) { fmt.Println("\n#### HasBase") // HasBase - snativeAddress, data := snativePermTestInputCALL("has_base", user[3], ptypes.Bond, false) + snativeAddress, pF, data := snativePermTestInputCALL("has_base", user[3], ptypes.Bond, false) testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data) - testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { + testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { // return value should be true or false as a 32 byte array... if !IsZeros(ret[:31]) || ret[31] != byte(1) { return fmt.Errorf("Expected 1. Got %X", ret) @@ -880,21 +882,21 @@ func TestSNativeCALL(t *testing.T) { fmt.Println("\n#### SetBase") // SetBase - snativeAddress, data = snativePermTestInputCALL("set_base", user[3], ptypes.Bond, false) + snativeAddress, pF, data = snativePermTestInputCALL("set_base", user[3], ptypes.Bond, false) testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data) - testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil }) - snativeAddress, data = snativePermTestInputCALL("has_base", user[3], ptypes.Bond, false) - testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { + testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { return nil }) + snativeAddress, pF, data = snativePermTestInputCALL("has_base", user[3], ptypes.Bond, false) + testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { // return value should be true or false as a 32 byte array... if !IsZeros(ret) { return fmt.Errorf("Expected 0. Got %X", ret) } return nil }) - snativeAddress, data = snativePermTestInputCALL("set_base", user[3], ptypes.CreateContract, true) - testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil }) - snativeAddress, data = snativePermTestInputCALL("has_base", user[3], ptypes.CreateContract, false) - testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { + snativeAddress, pF, data = snativePermTestInputCALL("set_base", user[3], ptypes.CreateContract, true) + testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { return nil }) + snativeAddress, pF, data = snativePermTestInputCALL("has_base", user[3], ptypes.CreateContract, false) + testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { // return value should be true or false as a 32 byte array... if !IsZeros(ret[:31]) || ret[31] != byte(1) { return fmt.Errorf("Expected 1. Got %X", ret) @@ -904,11 +906,11 @@ func TestSNativeCALL(t *testing.T) { fmt.Println("\n#### UnsetBase") // UnsetBase - snativeAddress, data = snativePermTestInputCALL("unset_base", user[3], ptypes.CreateContract, false) + snativeAddress, pF, data = snativePermTestInputCALL("unset_base", user[3], ptypes.CreateContract, false) testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data) - testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil }) - snativeAddress, data = snativePermTestInputCALL("has_base", user[3], ptypes.CreateContract, false) - testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { + testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { return nil }) + snativeAddress, pF, data = snativePermTestInputCALL("has_base", user[3], ptypes.CreateContract, false) + testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { if !IsZeros(ret) { return fmt.Errorf("Expected 0. Got %X", ret) } @@ -917,11 +919,11 @@ func TestSNativeCALL(t *testing.T) { fmt.Println("\n#### SetGlobal") // SetGlobalPerm - snativeAddress, data = snativePermTestInputCALL("set_global", user[3], ptypes.CreateContract, true) + snativeAddress, pF, data = snativePermTestInputCALL("set_global", user[3], ptypes.CreateContract, true) testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data) - testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil }) - snativeAddress, data = snativePermTestInputCALL("has_base", user[3], ptypes.CreateContract, false) - testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { + testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { return nil }) + snativeAddress, pF, data = snativePermTestInputCALL("has_base", user[3], ptypes.CreateContract, false) + testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { // return value should be true or false as a 32 byte array... if !IsZeros(ret[:31]) || ret[31] != byte(1) { return fmt.Errorf("Expected 1. Got %X", ret) @@ -931,9 +933,9 @@ func TestSNativeCALL(t *testing.T) { fmt.Println("\n#### HasRole") // HasRole - snativeAddress, data = snativeRoleTestInputCALL("has_role", user[3], "bumble") + snativeAddress, pF, data = snativeRoleTestInputCALL("has_role", user[3], "bumble") testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data) - testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { + testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { if !IsZeros(ret[:31]) || ret[31] != byte(1) { return fmt.Errorf("Expected 1. Got %X", ret) } @@ -942,18 +944,18 @@ func TestSNativeCALL(t *testing.T) { fmt.Println("\n#### AddRole") // AddRole - snativeAddress, data = snativeRoleTestInputCALL("has_role", user[3], "chuck") - testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { + snativeAddress, pF, data = snativeRoleTestInputCALL("has_role", user[3], "chuck") + testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { if !IsZeros(ret) { return fmt.Errorf("Expected 0. Got %X", ret) } return nil }) - snativeAddress, data = snativeRoleTestInputCALL("add_role", user[3], "chuck") + snativeAddress, pF, data = snativeRoleTestInputCALL("add_role", user[3], "chuck") testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data) - testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil }) - snativeAddress, data = snativeRoleTestInputCALL("has_role", user[3], "chuck") - testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { + testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { return nil }) + snativeAddress, pF, data = snativeRoleTestInputCALL("has_role", user[3], "chuck") + testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { if !IsZeros(ret[:31]) || ret[31] != byte(1) { return fmt.Errorf("Expected 1. Got %X", ret) } @@ -962,11 +964,11 @@ func TestSNativeCALL(t *testing.T) { fmt.Println("\n#### RmRole") // RmRole - snativeAddress, data = snativeRoleTestInputCALL("rm_role", user[3], "chuck") + snativeAddress, pF, data = snativeRoleTestInputCALL("rm_role", user[3], "chuck") testSNativeCALLExpectFail(t, blockCache, doug, snativeAddress, data) - testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { return nil }) - snativeAddress, data = snativeRoleTestInputCALL("has_role", user[3], "chuck") - testSNativeCALLExpectPass(t, blockCache, doug, snativeAddress, data, func(ret []byte) error { + testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { return nil }) + snativeAddress, pF, data = snativeRoleTestInputCALL("has_role", user[3], "chuck") + testSNativeCALLExpectPass(t, blockCache, doug, pF, snativeAddress, data, func(ret []byte) error { if !IsZeros(ret) { return fmt.Errorf("Expected 0. Got %X", ret) } @@ -1087,21 +1089,17 @@ func execTxWaitEvent(t *testing.T, blockCache *BlockCache, tx types.Tx, eventid // give a contract perms for an snative, call it, it calls the snative, but shouldn't have permission func testSNativeCALLExpectFail(t *testing.T, blockCache *BlockCache, doug *acm.Account, snativeAddress, data []byte) { - testSNativeCALL(t, false, blockCache, doug, snativeAddress, data, nil) + testSNativeCALL(t, false, blockCache, doug, 0, snativeAddress, data, nil) } // give a contract perms for an snative, call it, it calls the snative, ensure the check funciton (f) succeeds -func testSNativeCALLExpectPass(t *testing.T, blockCache *BlockCache, doug *acm.Account, snativeAddress, data []byte, f func([]byte) error) { - testSNativeCALL(t, true, blockCache, doug, snativeAddress, data, f) +func testSNativeCALLExpectPass(t *testing.T, blockCache *BlockCache, doug *acm.Account, snativePerm ptypes.PermFlag, snativeAddress, data []byte, f func([]byte) error) { + testSNativeCALL(t, true, blockCache, doug, snativePerm, snativeAddress, data, f) } -func testSNativeCALL(t *testing.T, expectPass bool, blockCache *BlockCache, doug *acm.Account, snativeAddress, data []byte, f func([]byte) error) { +func testSNativeCALL(t *testing.T, expectPass bool, blockCache *BlockCache, doug *acm.Account, snativePerm ptypes.PermFlag, snativeAddress, data []byte, f func([]byte) error) { if expectPass { - perm, err := ptypes.PermStringToFlag(TrimmedString(snativeAddress)) - if err != nil { - t.Fatal(err) - } - doug.Permissions.Base.Set(perm, true) + doug.Permissions.Base.Set(snativePerm, true) } var addr []byte contractCode := callContractCode(snativeAddress) @@ -1169,8 +1167,18 @@ func boolToWord256(v bool) Word256 { return LeftPadWord256([]byte{vint}) } -func snativePermTestInputCALL(name string, user *acm.PrivAccount, perm ptypes.PermFlag, val bool) (addr []byte, data []byte) { - addr = LeftPadWord256([]byte(name)).Postfix(20) +func permNameToFuncID(s string) []byte { + for k, v := range vm.PermsMap { + if s == v.Name { + b, _ := hex.DecodeString(k) + return b + } + } + panic("didn't find snative function signature!") +} + +func snativePermTestInputCALL(name string, user *acm.PrivAccount, perm ptypes.PermFlag, val bool) (addr []byte, pF ptypes.PermFlag, data []byte) { + addr = LeftPadWord256([]byte(vm.PermissionsContract)).Postfix(20) switch name { case "has_base", "unset_base": data = LeftPadBytes(user.Address, 32) @@ -1183,6 +1191,11 @@ func snativePermTestInputCALL(name string, user *acm.PrivAccount, perm ptypes.Pe data = Uint64ToWord256(uint64(perm)).Bytes() data = append(data, boolToWord256(val).Bytes()...) } + data = append(permNameToFuncID(name), data...) + var err error + if pF, err = ptypes.PermStringToFlag(name); err != nil { + panic(Fmt("failed to convert perm string (%s) to flag", name)) + } return } @@ -1200,10 +1213,16 @@ func snativePermTestInputTx(name string, user *acm.PrivAccount, perm ptypes.Perm return } -func snativeRoleTestInputCALL(name string, user *acm.PrivAccount, role string) (addr []byte, data []byte) { - addr = LeftPadWord256([]byte(name)).Postfix(20) +func snativeRoleTestInputCALL(name string, user *acm.PrivAccount, role string) (addr []byte, pF ptypes.PermFlag, data []byte) { + addr = LeftPadWord256([]byte(vm.PermissionsContract)).Postfix(20) data = LeftPadBytes(user.Address, 32) data = append(data, LeftPadBytes([]byte(role), 32)...) + data = append(permNameToFuncID(name), data...) + + var err error + if pF, err = ptypes.PermStringToFlag(name); err != nil { + panic(Fmt("failed to convert perm string (%s) to flag", name)) + } return } diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/types/priv_validator.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/types/priv_validator.go index ee6f9e27c9cee45d37ff30cea28b544fb801af3e..df62c1df4edaab54b033616fff738f844977bc9b 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/types/priv_validator.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/types/priv_validator.go @@ -42,7 +42,7 @@ type PrivValidator struct { LastRound int `json:"last_round"` LastStep int8 `json:"last_step"` - // NOTE: A safer implemention leaves PrivKey empty and uses a secure key signing service. + // PrivKey should be empty if a Signer other than the default is being used. PrivKey acm.PrivKeyEd25519 `json:"priv_key"` signer Signer @@ -52,6 +52,9 @@ type PrivValidator struct { mtx sync.Mutex } +// XXX: This is used to sign votes. +// It is the caller's duty to verify the msg before calling Sign, +// eg. to avoid double signing. type Signer interface { Sign(msg []byte) acm.SignatureEd25519 } diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/snative.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/snative.go index a9a5c9ee4dee933b043464852a53972c79eb25ff..b497364d7d111a77c1c64cadda65a29ec8adb742 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/snative.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/vm/snative.go @@ -1,38 +1,98 @@ package vm import ( + "encoding/hex" "fmt" . "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/common" ptypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/permission/types" ) -// TODO: ABI //------------------------------------------------------------------------------------------------ // Registered SNative contracts +var PermissionsContract = "permissions_contract" + func registerSNativeContracts() { - registeredNativeContracts[LeftPadWord256([]byte("has_base"))] = hasBasePerm - registeredNativeContracts[LeftPadWord256([]byte("set_base"))] = setBasePerm - registeredNativeContracts[LeftPadWord256([]byte("unset_base"))] = unsetBasePerm - registeredNativeContracts[LeftPadWord256([]byte("set_global"))] = setGlobalPerm - registeredNativeContracts[LeftPadWord256([]byte("has_role"))] = hasRole - registeredNativeContracts[LeftPadWord256([]byte("add_role"))] = addRole - registeredNativeContracts[LeftPadWord256([]byte("rm_role"))] = rmRole + registeredNativeContracts[LeftPadWord256([]byte(PermissionsContract))] = permissionsContract + + /* + // we could expose these but we moved permission and args checks into the permissionsContract + // so calling them would be unsafe ... + registeredNativeContracts[LeftPadWord256([]byte("has_base"))] = has_base + registeredNativeContracts[LeftPadWord256([]byte("set_base"))] = set_base + registeredNativeContracts[LeftPadWord256([]byte("unset_base"))] = unset_base + registeredNativeContracts[LeftPadWord256([]byte("set_global"))] = set_global + registeredNativeContracts[LeftPadWord256([]byte("has_role"))] = has_role + registeredNativeContracts[LeftPadWord256([]byte("add_role"))] = add_role + registeredNativeContracts[LeftPadWord256([]byte("rm_role"))] = rm_role + */ } //----------------------------------------------------------------------------- // snative are native contracts that can access and modify an account's permissions -// TODO: catch errors, log em, return 0s to the vm (should some errors cause exceptions though?) +type SNativeFuncDescription struct { + Name string + NArgs int + PermFlag ptypes.PermFlag + F NativeContract +} + +/* The solidity interface used to generate the abi function ids below +contract Permissions { + function has_base(address addr, int permFlag) constant returns (bool value) {} + function set_base(address addr, int permFlag, bool value) constant returns (bool val) {} + function unset_base(address addr, int permFlag) constant returns (int pf) {} + function set_global(address addr, int permFlag, bool value) constant returns (int pf) {} + function has_role(address addr, string role) constant returns (bool val) {} + function add_role(address addr, string role) constant returns (bool added) {} + function rm_role(address addr, string role) constant returns (bool removed) {} +} +*/ + +// function identifiers from the solidity abi +var PermsMap = map[string]SNativeFuncDescription{ + "054556ac": SNativeFuncDescription{"has_role", 2, ptypes.HasRole, has_role}, + "180d26f2": SNativeFuncDescription{"unset_base", 2, ptypes.UnsetBase, unset_base}, + "3a3fcc59": SNativeFuncDescription{"set_global", 2, ptypes.SetGlobal, set_global}, + "9a1c4141": SNativeFuncDescription{"add_role", 2, ptypes.AddRole, add_role}, + "9ea53314": SNativeFuncDescription{"set_base", 3, ptypes.SetBase, set_base}, + "bb37737a": SNativeFuncDescription{"has_base", 2, ptypes.HasBase, has_base}, + "ded3350a": SNativeFuncDescription{"rm_role", 2, ptypes.RmRole, rm_role}, +} + +func permissionsContract(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) { + if len(args) < 4 { + return nil, fmt.Errorf("permissionsContract expects at least a 4-byte function identifier") + } + + // map solidity abi function id to snative + funcIDbytes := args[:4] + args = args[4:] + funcID := hex.EncodeToString(funcIDbytes) + d, ok := PermsMap[funcID] + if !ok { + return nil, fmt.Errorf("unknown permissionsContract funcID %s", funcID) + } -func hasBasePerm(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) { - if !HasPermission(appState, caller, ptypes.HasBase) { - return nil, ErrInvalidPermission{caller.Address, "has_base"} + // check if we have permission to call this function + if !HasPermission(appState, caller, d.PermFlag) { + return nil, ErrInvalidPermission{caller.Address, d.Name} } - if len(args) != 2*32 { - return nil, fmt.Errorf("hasBasePerm() takes two arguments (address, permFlag)") + + // ensure there are enough arguments + if len(args) != d.NArgs*32 { + return nil, fmt.Errorf("%s() takes %d arguments", d.Name) } + + // call the function + return d.F(appState, caller, args, gas) +} + +// TODO: catch errors, log em, return 0s to the vm (should some errors cause exceptions though?) + +func has_base(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) { addr, permNum := returnTwoArgs(args) vmAcc := appState.GetAccount(addr) if vmAcc == nil { @@ -42,23 +102,12 @@ func hasBasePerm(appState AppState, caller *Account, args []byte, gas *int64) (o if !ValidPermN(permN) { return nil, ptypes.ErrInvalidPermission(permN) } - var permInt byte - if HasPermission(appState, vmAcc, permN) { - permInt = 0x1 - } else { - permInt = 0x0 - } + permInt := byteFromBool(HasPermission(appState, vmAcc, permN)) dbg.Printf("snative.hasBasePerm(0x%X, %b) = %v\n", addr.Postfix(20), permN, permInt) return LeftPadWord256([]byte{permInt}).Bytes(), nil } -func setBasePerm(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) { - if !HasPermission(appState, caller, ptypes.SetBase) { - return nil, ErrInvalidPermission{caller.Address, "set_base"} - } - if len(args) != 3*32 { - return nil, fmt.Errorf("setBase() takes three arguments (address, permFlag, permission value)") - } +func set_base(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) { addr, permNum, perm := returnThreeArgs(args) vmAcc := appState.GetAccount(addr) if vmAcc == nil { @@ -77,13 +126,7 @@ func setBasePerm(appState AppState, caller *Account, args []byte, gas *int64) (o return perm.Bytes(), nil } -func unsetBasePerm(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) { - if !HasPermission(appState, caller, ptypes.UnsetBase) { - return nil, ErrInvalidPermission{caller.Address, "unset_base"} - } - if len(args) != 2*32 { - return nil, fmt.Errorf("unsetBase() takes two arguments (address, permFlag)") - } +func unset_base(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) { addr, permNum := returnTwoArgs(args) vmAcc := appState.GetAccount(addr) if vmAcc == nil { @@ -101,13 +144,7 @@ func unsetBasePerm(appState AppState, caller *Account, args []byte, gas *int64) return permNum.Bytes(), nil } -func setGlobalPerm(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) { - if !HasPermission(appState, caller, ptypes.SetGlobal) { - return nil, ErrInvalidPermission{caller.Address, "set_global"} - } - if len(args) != 2*32 { - return nil, fmt.Errorf("setGlobal() takes two arguments (permFlag, permission value)") - } +func set_global(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) { permNum, perm := returnTwoArgs(args) vmAcc := appState.GetAccount(ptypes.GlobalPermissionsAddress256) if vmAcc == nil { @@ -126,72 +163,39 @@ func setGlobalPerm(appState AppState, caller *Account, args []byte, gas *int64) return perm.Bytes(), nil } -func hasRole(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) { - if !HasPermission(appState, caller, ptypes.HasRole) { - return nil, ErrInvalidPermission{caller.Address, "has_role"} - } - if len(args) != 2*32 { - return nil, fmt.Errorf("hasRole() takes two arguments (address, role)") - } +func has_role(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) { addr, role := returnTwoArgs(args) vmAcc := appState.GetAccount(addr) if vmAcc == nil { return nil, fmt.Errorf("Unknown account %X", addr) } roleS := string(role.Bytes()) - var permInt byte - if vmAcc.Permissions.HasRole(roleS) { - permInt = 0x1 - } else { - permInt = 0x0 - } + permInt := byteFromBool(vmAcc.Permissions.HasRole(roleS)) dbg.Printf("snative.hasRole(0x%X, %s) = %v\n", addr.Postfix(20), roleS, permInt > 0) return LeftPadWord256([]byte{permInt}).Bytes(), nil } -func addRole(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) { - if !HasPermission(appState, caller, ptypes.AddRole) { - return nil, ErrInvalidPermission{caller.Address, "add_role"} - } - if len(args) != 2*32 { - return nil, fmt.Errorf("addRole() takes two arguments (address, role)") - } +func add_role(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) { addr, role := returnTwoArgs(args) vmAcc := appState.GetAccount(addr) if vmAcc == nil { return nil, fmt.Errorf("Unknown account %X", addr) } roleS := string(role.Bytes()) - var permInt byte - if vmAcc.Permissions.AddRole(roleS) { - permInt = 0x1 - } else { - permInt = 0x0 - } + permInt := byteFromBool(vmAcc.Permissions.AddRole(roleS)) appState.UpdateAccount(vmAcc) dbg.Printf("snative.addRole(0x%X, %s) = %v\n", addr.Postfix(20), roleS, permInt > 0) return LeftPadWord256([]byte{permInt}).Bytes(), nil } -func rmRole(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) { - if !HasPermission(appState, caller, ptypes.RmRole) { - return nil, ErrInvalidPermission{caller.Address, "rm_role"} - } - if len(args) != 2*32 { - return nil, fmt.Errorf("rmRole() takes two arguments (address, role)") - } +func rm_role(appState AppState, caller *Account, args []byte, gas *int64) (output []byte, err error) { addr, role := returnTwoArgs(args) vmAcc := appState.GetAccount(addr) if vmAcc == nil { return nil, fmt.Errorf("Unknown account %X", addr) } roleS := string(role.Bytes()) - var permInt byte - if vmAcc.Permissions.RmRole(roleS) { - permInt = 0x1 - } else { - permInt = 0x0 - } + permInt := byteFromBool(vmAcc.Permissions.RmRole(roleS)) appState.UpdateAccount(vmAcc) dbg.Printf("snative.rmRole(0x%X, %s) = %v\n", addr.Postfix(20), roleS, permInt > 0) return LeftPadWord256([]byte{permInt}).Bytes(), nil @@ -231,3 +235,10 @@ func returnThreeArgs(args []byte) (a Word256, b Word256, c Word256) { copy(c[:], args[64:96]) return } + +func byteFromBool(b bool) byte { + if b { + return 0x1 + } + return 0x0 +}