Skip to content
This repository has been archived by the owner on May 13, 2022. It is now read-only.

Commit

Permalink
Add test for Dispatch
Browse files Browse the repository at this point in the history
  • Loading branch information
Silas Davis committed Feb 17, 2017
1 parent aa61e95 commit 96df876
Show file tree
Hide file tree
Showing 8 changed files with 87 additions and 27 deletions.
2 changes: 1 addition & 1 deletion event/event_cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"github.com/stretchr/testify/assert"
)

var mockInterval = 10 * time.Millisecond
var mockInterval = 40 * time.Millisecond

type mockSub struct {
subId string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package vm
import (
"fmt"

. "github.com/eris-ltd/eris-db/manager/eris-mint/evm"
"github.com/eris-ltd/eris-db/manager/eris-mint/evm/sha3"
. "github.com/eris-ltd/eris-db/word256"
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"reflect"
"testing"

. "github.com/eris-ltd/eris-db/manager/eris-mint/evm"
. "github.com/eris-ltd/eris-db/manager/eris-mint/evm/opcodes"
"github.com/eris-ltd/eris-db/txs"
. "github.com/eris-ltd/eris-db/word256"
Expand Down
3 changes: 3 additions & 0 deletions manager/eris-mint/evm/opcodes/opcodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package opcodes
import (
"fmt"

"github.com/eris-ltd/eris-db/word256"
"gopkg.in/fatih/set.v0"
)

Expand Down Expand Up @@ -378,6 +379,8 @@ func Bytecode(bytelikes ...interface{}) []byte {
if int64(bytes[i]) != b {
panic(fmt.Sprintf("The int64 %v does not fit inside a byte", b))
}
case word256.Word256:
return Concat(bytes[:i], b[:], Bytecode(bytelikes[i+1:]...))
case []byte:
// splice
return Concat(bytes[:i], b, Bytecode(bytelikes[i+1:]...))
Expand Down
20 changes: 12 additions & 8 deletions manager/eris-mint/evm/snative.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ func SNativeContracts() map[string]SNativeContractDescription {
* @return result value passed in
`,
"set_base",
[]SolidityArg{arg("_account", SolidityAddress),
[]SolidityArg{
arg("_account", SolidityAddress),
arg("_authorization", permFlagType),
arg("_value", permFlagType)},
ret("result", SolidityBool),
Expand All @@ -135,7 +136,8 @@ func SNativeContracts() map[string]SNativeContractDescription {
* @return result whether account has base authorization set
`,
"has_base",
[]SolidityArg{arg("_account", SolidityAddress),
[]SolidityArg{
arg("_account", SolidityAddress),
arg("_authorization", permFlagType)},
ret("result", SolidityBool),
ptypes.HasBase,
Expand All @@ -148,21 +150,21 @@ func SNativeContracts() map[string]SNativeContractDescription {
* @return authorization base authorization passed in
`,
"unset_base",
[]SolidityArg{arg("_account", SolidityAddress),
[]SolidityArg{
arg("_account", SolidityAddress),
arg("_authorization", permFlagType)},
ret("authorization", permFlagType),
ptypes.UnsetBase,
unset_base},

SNativeFuncDescription{`
* @notice Sets global (default) value for a base authorization
* @param _account account
* @param _authorization base authorization
* @param _value value of base authorization
* @return authorization base authorization passed in
`,
"set_global",
[]SolidityArg{arg("_account", SolidityAddress),
[]SolidityArg{
arg("_authorization", permFlagType),
arg("_value", permFlagType)},
ret("authorization", permFlagType),
Expand Down Expand Up @@ -199,11 +201,14 @@ func NewSNativeContract(comment, name string, functions ...SNativeFuncDescriptio
}
}

// This function is designed to be called from the EVM once a SNative contract
// has been selected. It is also placed in a registry by registerSNativeContracts
// So it can be looked up by SNative address
func (contract *SNativeContractDescription) Dispatch(appState AppState,
caller *Account, args []byte, gas *int64) (output []byte, err error) {
caller *Account, args []byte, gas *int64) (output []byte, err error) {
if len(args) < FuncIDLength {
return Zero256.Bytes(), fmt.Errorf("SNatives dispatch requires a 4-byte function "+
"identifier but arguments are only %s bytes long", len(args))
"identifier but arguments are only %s bytes long", len(args))
}

function, err := contract.FunctionByID(firstFourBytes(args))
Expand All @@ -228,7 +233,6 @@ func (contract *SNativeContractDescription) Dispatch(appState AppState,
return function.F(appState, caller, remainingArgs, gas)
}


func (contract *SNativeContractDescription) Address() Word256 {
return LeftPadWord256([]byte(contract.Name))
}
Expand Down
84 changes: 69 additions & 15 deletions manager/eris-mint/evm/snative_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,49 +4,85 @@ import (
"encoding/hex"
"testing"

. "github.com/eris-ltd/eris-db/word256"
"github.com/stretchr/testify/assert"
"fmt"
. "github.com/eris-ltd/eris-db/manager/eris-mint/evm/opcodes"
ptypes "github.com/eris-ltd/eris-db/permission/types"
)

/* Compiling the Permissions solidity contract at
(generated by Solidity() function)
https://ethereum.github.io/browser-solidity yields:
Functions
3fbf7da5 add_role(address,bytes32)
744f5998 has_base(address,uint64)
e8145855 has_role(address,bytes32)
28fd0194 rm_role(address,bytes32)
3f0ebb30 set_base(address,uint64,uint64)
67dc6f70 set_global(address,uint64,uint64)
d54a562d set_global(uint64,uint64)
73448c99 unset_base(address,uint64)
*/

func TestPermissionsContract(t *testing.T) {
registerNativeContracts()
func TestPermissionsContractSignatures(t *testing.T) {
contract := SNativeContracts()["permissions_contract"]

assertContractFunction(t, contract, "3fbf7da5",
assertFunctionIDSignature(t, contract, "3fbf7da5",
"add_role(address,bytes32)")

assertContractFunction(t, contract, "744f5998",
assertFunctionIDSignature(t, contract, "744f5998",
"has_base(address,uint64)")

assertContractFunction(t, contract, "e8145855",
assertFunctionIDSignature(t, contract, "e8145855",
"has_role(address,bytes32)")

assertContractFunction(t, contract, "28fd0194",
assertFunctionIDSignature(t, contract, "28fd0194",
"rm_role(address,bytes32)")

assertContractFunction(t, contract, "3f0ebb30",
assertFunctionIDSignature(t, contract, "3f0ebb30",
"set_base(address,uint64,uint64)")

assertContractFunction(t, contract, "67dc6f70",
"set_global(address,uint64,uint64)")
assertFunctionIDSignature(t, contract, "d54a562d",
"set_global(uint64,uint64)")

assertContractFunction(t, contract, "73448c99",
assertFunctionIDSignature(t, contract, "73448c99",
"unset_base(address,uint64)")
}

func TestSNativeContractDescription_Dispatch(t *testing.T) {
contract := SNativeContracts()["permissions_contract"]
state := newAppState()
caller := &Account{
Address: addr(1,1,1),
}
grantee := &Account{
Address: addr(2,2,2),
}
state.UpdateAccount(grantee)

function, err := contract.FunctionByName("add_role")
if err != nil {
t.Fatalf("Could not get function: %s", err)
}
funcID := function.ID()
gas := int64(1000)

retValue, err := contract.Dispatch(state, caller, Bytecode(funcID[:],
grantee.Address, permFlagToWord256(ptypes.CreateAccount)), &gas)
assert.Error(t, err)
if err != nil {
assert.Contains(t, err.Error(), "does not have permission")
}

caller.Permissions = allAccountPermissions()
retValue, err = contract.Dispatch(state, caller, Bytecode(funcID[:],
grantee.Address, permFlagToWord256(ptypes.CreateAccount)), &gas)
assert.NoError(t, err)
assert.Equal(t, retValue, LeftPadBytes([]byte{1},32))
}

func TestSNativeFuncTemplate(t *testing.T) {
contract := SNativeContracts()["permissions_contract"]
function, err := contract.FunctionByName("rm_role")
Expand All @@ -67,19 +103,20 @@ func TestSNativeContractTemplate(t *testing.T) {
fmt.Println(solidity)
}

//
// Helpers

func assertContractFunction(t *testing.T, contract SNativeContractDescription,
//
func assertFunctionIDSignature(t *testing.T, contract SNativeContractDescription,
funcIDHex string, expectedSignature string) {
function, err := contract.FunctionByID(fourBytesFromHex(t, funcIDHex))
function, err := contract.FunctionByID(funcIDFromHex(t, funcIDHex))
assert.NoError(t, err,
"Error retrieving SNativeFunctionDescription with ID %s", funcIDHex)
if err == nil {
assert.Equal(t, expectedSignature, function.Signature())
}
}

func fourBytesFromHex(t *testing.T, hexString string) [4]byte {
func funcIDFromHex(t *testing.T, hexString string) FuncID {
bs, err := hex.DecodeString(hexString)
assert.NoError(t, err, "Could not decode hex string '%s'", hexString)
if len(bs) != 4 {
Expand All @@ -89,3 +126,20 @@ func fourBytesFromHex(t *testing.T, hexString string) [4]byte {
return firstFourBytes(bs)
}

func permFlagToWord256(permFlag ptypes.PermFlag) Word256 {
return Uint64ToWord256(uint64(permFlag))
}

func addr(rightBytes... uint8) Word256 {
return LeftPadWord256(rightBytes)
}

func allAccountPermissions() ptypes.AccountPermissions {
return ptypes.AccountPermissions{
Base: ptypes.BasePermissions{
Perms: ptypes.AllPermFlags,
SetBit: ptypes.AllPermFlags,
},
Roles: []string{},
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (

"errors"

. "github.com/eris-ltd/eris-db/manager/eris-mint/evm"
. "github.com/eris-ltd/eris-db/manager/eris-mint/evm/opcodes"
ptypes "github.com/eris-ltd/eris-db/permission/types"
"github.com/eris-ltd/eris-db/txs"
Expand Down
2 changes: 2 additions & 0 deletions manager/eris-mint/state/tx_cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ type TxCache struct {
storages map[Tuple256]Word256
}

var _ vm.AppState = &TxCache{}

func NewTxCache(backend *BlockCache) *TxCache {
return &TxCache{
backend: backend,
Expand Down

0 comments on commit 96df876

Please sign in to comment.