fire events on snative and allow from CallTx

This commit is contained in:
Ethan Buchman
2015-05-21 17:58:28 -04:00
committed by Jae Kwon
parent d824e1b731
commit b11012026d
4 changed files with 42 additions and 16 deletions

View File

@@ -79,6 +79,9 @@ func (p *BasePermissions) Unset(ty PermFlag) error {
} }
func (p *BasePermissions) Copy() *BasePermissions { func (p *BasePermissions) Copy() *BasePermissions {
if p == nil {
return nil
}
return &BasePermissions{ return &BasePermissions{
Perms: p.Perms, Perms: p.Perms,
SetBit: p.SetBit, SetBit: p.SetBit,
@@ -140,6 +143,9 @@ func (aP *AccountPermissions) RmRole(role string) bool {
} }
func (aP *AccountPermissions) Copy() *AccountPermissions { func (aP *AccountPermissions) Copy() *AccountPermissions {
if aP == nil {
return nil
}
r := make([]string, len(aP.Roles)) r := make([]string, len(aP.Roles))
copy(r, aP.Roles) copy(r, aP.Roles)
return &AccountPermissions{ return &AccountPermissions{

View File

@@ -405,6 +405,7 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea
// this may be nil if we are still in mempool and contract was created in same block as this tx // this may be nil if we are still in mempool and contract was created in same block as this tx
// but that's fine, because the account will be created properly when the create tx runs in the block // but that's fine, because the account will be created properly when the create tx runs in the block
// and then this won't return nil. otherwise, we take their fee // and then this won't return nil. otherwise, we take their fee
// it may also be nil if its an snative (not a "real" account)
outAcc = blockCache.GetAccount(tx.Address) outAcc = blockCache.GetAccount(tx.Address)
} }
@@ -431,9 +432,16 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea
} }
) )
// Maybe create a new callee account if // get or create callee
// this transaction is creating a new contract.
if !createAccount { if !createAccount {
if outAcc == nil {
// check if its an snative
if _, ok := vm.RegisteredSNativeContracts[LeftPadWord256(tx.Address)]; ok {
// set the outAcc (simply a placeholder until we reach the call)
outAcc = &account.Account{Address: tx.Address}
}
}
if outAcc == nil || len(outAcc.Code) == 0 { if outAcc == nil || len(outAcc.Code) == 0 {
// if you call an account that doesn't exist // if you call an account that doesn't exist
// or an account with no code then we take fees (sorry pal) // or an account with no code then we take fees (sorry pal)
@@ -456,13 +464,15 @@ func ExecTx(blockCache *BlockCache, tx_ types.Tx, runCall bool, evc events.Firea
log.Debug(Fmt("Calling contract %X with code %X", callee.Address, callee.Code)) log.Debug(Fmt("Calling contract %X with code %X", callee.Address, callee.Code))
} else { } else {
callee = txCache.CreateAccount(caller) callee = txCache.CreateAccount(caller)
txCache.UpdateAccount(callee)
log.Debug(Fmt("Created new account %X", callee.Address)) log.Debug(Fmt("Created new account %X", callee.Address))
code = tx.Data code = tx.Data
} }
log.Debug(Fmt("Code for this contract: %X", code)) log.Debug(Fmt("Code for this contract: %X", code))
txCache.UpdateAccount(caller) // because we adjusted by input above, and bumped nonce maybe. txCache.UpdateAccount(caller) // because we bumped nonce
txCache.UpdateAccount(callee) // because we adjusted by input above. txCache.UpdateAccount(callee) // so the txCache knows about the callee and the transfer takes effect
vmach := vm.NewVM(txCache, params, caller.Address, account.HashSignBytes(_s.ChainID, tx)) vmach := vm.NewVM(txCache, params, caller.Address, account.HashSignBytes(_s.ChainID, tx))
vmach.SetFireable(evc) vmach.SetFireable(evc)

View File

@@ -45,7 +45,7 @@ const (
TopSNativePermission ptypes.PermFlag = FirstSNativePerm << (NumSNativePermissions - 1) TopSNativePermission ptypes.PermFlag = FirstSNativePerm << (NumSNativePermissions - 1)
) )
var registeredSNativeContracts = map[Word256]ptypes.PermFlag{ var RegisteredSNativeContracts = map[Word256]ptypes.PermFlag{
LeftPadWord256([]byte("hasBasePerm")): HasBasePerm, LeftPadWord256([]byte("hasBasePerm")): HasBasePerm,
LeftPadWord256([]byte("setBasePerm")): SetBasePerm, LeftPadWord256([]byte("setBasePerm")): SetBasePerm,
LeftPadWord256([]byte("unsetBasePerm")): UnsetBasePerm, LeftPadWord256([]byte("unsetBasePerm")): UnsetBasePerm,
@@ -60,7 +60,7 @@ var registeredSNativeContracts = map[Word256]ptypes.PermFlag{
type SNativeContract func(acc *Account, input []byte) (output []byte, err error) type SNativeContract func(acc *Account, input []byte) (output []byte, err error)
func (vm *VM) SNativeContract(name Word256) SNativeContract { func (vm *VM) SNativeContract(name Word256) SNativeContract {
flag := registeredSNativeContracts[name] flag := RegisteredSNativeContracts[name]
switch flag { switch flag {
case HasBasePerm: case HasBasePerm:
return vm.hasBasePerm return vm.hasBasePerm

View File

@@ -117,6 +117,17 @@ func (vm *VM) Call(caller, callee *Account, code, input []byte, value int64, gas
} }
}() }()
// if code is empty, callee may be snative contract
if vm.snative && len(code) == 0 {
if snativeContract := vm.SNativeContract(callee.Address); snativeContract != nil {
output, err = snativeContract(caller, input)
if err != nil {
*exception = err.Error()
}
return
}
}
if err = transfer(caller, callee, value); err != nil { if err = transfer(caller, callee, value); err != nil {
*exception = err.Error() *exception = err.Error()
return return
@@ -746,9 +757,6 @@ 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 snativeContract := vm.SNativeContract(addr); vm.snative && snativeContract != nil {
// Secure native contract (with access to chain state)
ret, err = snativeContract(callee, args)
} else { } else {
// EVM contract // EVM contract
if ok = useGas(gas, GasGetAccount); !ok { if ok = useGas(gas, GasGetAccount); !ok {
@@ -766,13 +774,15 @@ 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 {
// if we have not seen the account before, create it if _, ok := RegisteredSNativeContracts[addr]; vm.snative && ok {
// so we can send funds acc = &Account{Address: addr}
if vm.perms && !vm.HasPermission(caller, ptypes.CreateAccount) { } else {
return nil, ErrPermission{"create_account"} // if we have not seen the account before, create it
} // so we can send funds
acc = &Account{ if vm.perms && !vm.HasPermission(caller, ptypes.CreateAccount) {
Address: addr, return nil, ErrPermission{"create_account"}
}
acc = &Account{Address: addr}
} }
vm.appState.UpdateAccount(acc) vm.appState.UpdateAccount(acc)
} }