mirror of
https://github.com/fluencelabs/tendermint
synced 2025-04-25 06:42:16 +00:00
RegisteredSNativeContracts
This commit is contained in:
parent
ecd231a8eb
commit
ab536618e0
@ -424,8 +424,8 @@ func ExecTx(blockCache *BlockCache, tx types.Tx, runCall bool, evc events.Fireab
|
|||||||
|
|
||||||
if outAcc == nil || len(outAcc.Code) == 0 {
|
if outAcc == nil || len(outAcc.Code) == 0 {
|
||||||
// check if its an snative
|
// check if its an snative
|
||||||
trimmedAddr := TrimmedString(tx.Address)
|
// TODO: should we restrict from calling natives too?
|
||||||
if _, unknownPermErr := ptypes.SNativeStringToPermFlag(string(trimmedAddr)); unknownPermErr == nil {
|
if _, ok := vm.RegisteredSNativeContracts[LeftPadWord256(tx.Address)]; ok {
|
||||||
return fmt.Errorf("SNatives can not be called using CallTx. Either use a contract or a SNativeTx")
|
return fmt.Errorf("SNatives can not be called using CallTx. Either use a contract or a SNativeTx")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,11 @@ import (
|
|||||||
var nativeContracts = make(map[Word256]NativeContract)
|
var nativeContracts = make(map[Word256]NativeContract)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
registerNativeContracts()
|
||||||
|
registerSNativeContracts()
|
||||||
|
}
|
||||||
|
|
||||||
|
func registerNativeContracts() {
|
||||||
nativeContracts[Int64ToWord256(1)] = ecrecoverFunc
|
nativeContracts[Int64ToWord256(1)] = ecrecoverFunc
|
||||||
nativeContracts[Int64ToWord256(2)] = sha256Func
|
nativeContracts[Int64ToWord256(2)] = sha256Func
|
||||||
nativeContracts[Int64ToWord256(3)] = ripemd160Func
|
nativeContracts[Int64ToWord256(3)] = ripemd160Func
|
||||||
|
@ -22,8 +22,24 @@ type SNativeContract func(appState AppState, input []byte) (output []byte, err e
|
|||||||
//------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------
|
||||||
// Registered SNative contracts
|
// Registered SNative contracts
|
||||||
|
|
||||||
|
var RegisteredSNativeContracts = make(map[Word256]*snativeInfo)
|
||||||
|
|
||||||
|
func registerSNativeContracts() {
|
||||||
|
RegisteredSNativeContracts[LeftPadWord256([]byte("HasBase"))] = getSNativeInfo("HasBase")
|
||||||
|
RegisteredSNativeContracts[LeftPadWord256([]byte("SetBase"))] = getSNativeInfo("SetBase")
|
||||||
|
RegisteredSNativeContracts[LeftPadWord256([]byte("UnsetBase"))] = getSNativeInfo("UnsetBase")
|
||||||
|
RegisteredSNativeContracts[LeftPadWord256([]byte("SetGlobal"))] = getSNativeInfo("SetGlobal")
|
||||||
|
RegisteredSNativeContracts[LeftPadWord256([]byte("HasRole"))] = getSNativeInfo("HasRole")
|
||||||
|
RegisteredSNativeContracts[LeftPadWord256([]byte("AddRole"))] = getSNativeInfo("AddRole")
|
||||||
|
RegisteredSNativeContracts[LeftPadWord256([]byte("RmRole"))] = getSNativeInfo("RmRole")
|
||||||
|
}
|
||||||
|
|
||||||
// sets the number of arguments, a friendly error message, and the snative function ("executable")
|
// sets the number of arguments, a friendly error message, and the snative function ("executable")
|
||||||
func getSNativeInfo(permFlag ptypes.PermFlag) *snativeInfo {
|
func getSNativeInfo(permString string) *snativeInfo {
|
||||||
|
permFlag, err := ptypes.SNativeStringToPermFlag(permString)
|
||||||
|
if err != nil {
|
||||||
|
PanicSanity(err)
|
||||||
|
}
|
||||||
si := &snativeInfo{PermFlag: permFlag}
|
si := &snativeInfo{PermFlag: permFlag}
|
||||||
var errS string
|
var errS string
|
||||||
switch permFlag {
|
switch permFlag {
|
||||||
|
31
vm/vm.go
31
vm/vm.go
@ -110,17 +110,17 @@ func (vm *VM) fireEvent(exception *string, output *[]byte, caller, callee *Accou
|
|||||||
|
|
||||||
// call an snative contract (includes event processing)
|
// call an snative contract (includes event processing)
|
||||||
// addr and permFlag refer to the same snative's address and it's permFlag
|
// addr and permFlag refer to the same snative's address and it's permFlag
|
||||||
func (vm *VM) callSNative(addr Word256, permFlag ptypes.PermFlag, caller *Account, input []byte, value int64, gas *int64) (ret []byte, err error) {
|
func (vm *VM) callSNative(addr Word256, snInfo *snativeInfo, caller *Account, input []byte) (ret []byte, err error) {
|
||||||
exception := new(string)
|
exception := new(string)
|
||||||
// fire the post call event (including exception if applicable)
|
// fire the post call event (including exception if applicable)
|
||||||
|
value, gas := int64(0), new(int64)
|
||||||
defer vm.fireEvent(exception, &ret, caller, &Account{Address: addr}, input, value, gas)
|
defer vm.fireEvent(exception, &ret, caller, &Account{Address: addr}, input, value, gas)
|
||||||
|
|
||||||
if !HasPermission(vm.appState, caller, permFlag) {
|
if !HasPermission(vm.appState, caller, snInfo.PermFlag) {
|
||||||
err = ErrInvalidPermission{caller.Address, addr.TrimmedString()}
|
err = ErrInvalidPermission{caller.Address, addr.TrimmedString()}
|
||||||
*exception = err.Error()
|
*exception = err.Error()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
snInfo := getSNativeInfo(permFlag)
|
|
||||||
if len(input) != snInfo.NArgs*32 {
|
if len(input) != snInfo.NArgs*32 {
|
||||||
err = snInfo.ArgsError
|
err = snInfo.ArgsError
|
||||||
*exception = err.Error()
|
*exception = err.Error()
|
||||||
@ -780,6 +780,8 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
|
|||||||
if nativeContract := nativeContracts[addr]; nativeContract != nil {
|
if nativeContract := nativeContracts[addr]; nativeContract != nil {
|
||||||
// Native contract
|
// Native contract
|
||||||
ret, err = nativeContract(args, &gasLimit)
|
ret, err = nativeContract(args, &gasLimit)
|
||||||
|
} else if snInfo, ok := RegisteredSNativeContracts[addr]; ok {
|
||||||
|
ret, err = vm.callSNative(addr, snInfo, callee, input)
|
||||||
} else {
|
} else {
|
||||||
// EVM contract
|
// EVM contract
|
||||||
if ok = useGas(gas, GasGetAccount); !ok {
|
if ok = useGas(gas, GasGetAccount); !ok {
|
||||||
@ -797,23 +799,14 @@ func (vm *VM) call(caller, callee *Account, code, input []byte, value int64, gas
|
|||||||
ret, err = vm.Call(callee, callee, acc.Code, args, value, gas)
|
ret, err = vm.Call(callee, callee, acc.Code, args, value, gas)
|
||||||
} else {
|
} else {
|
||||||
if acc == nil {
|
if acc == nil {
|
||||||
// nil account means either the address is the name of an snative,
|
// nil account means we're sending funds to a new account
|
||||||
// or we're sending funds to a new account
|
if !HasPermission(vm.appState, caller, ptypes.CreateAccount) {
|
||||||
|
return nil, ErrPermission{"create_account"}
|
||||||
// trim the 0s off the address and check if its known
|
|
||||||
trimmedAddr := addr.TrimmedString()
|
|
||||||
if permFlag, unknownPermErr := ptypes.SNativeStringToPermFlag(trimmedAddr); unknownPermErr == nil {
|
|
||||||
ret, err = vm.callSNative(addr, permFlag, callee, input, value, gas)
|
|
||||||
} else {
|
|
||||||
// if we have not seen the account before, create it
|
|
||||||
if !HasPermission(vm.appState, caller, ptypes.CreateAccount) {
|
|
||||||
return nil, ErrPermission{"create_account"}
|
|
||||||
}
|
|
||||||
acc = &Account{Address: addr}
|
|
||||||
vm.appState.UpdateAccount(acc)
|
|
||||||
// send funds to new account
|
|
||||||
ret, err = vm.Call(callee, acc, acc.Code, args, value, gas)
|
|
||||||
}
|
}
|
||||||
|
acc = &Account{Address: addr}
|
||||||
|
vm.appState.UpdateAccount(acc)
|
||||||
|
// send funds to new account
|
||||||
|
ret, err = vm.Call(callee, acc, acc.Code, args, value, gas)
|
||||||
} else {
|
} else {
|
||||||
// call standard contract
|
// call standard contract
|
||||||
ret, err = vm.Call(callee, acc, acc.Code, args, value, gas)
|
ret, err = vm.Call(callee, acc, acc.Code, args, value, gas)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user