aboutsummaryrefslogtreecommitdiffstats
path: root/core/state_transition.go
diff options
context:
space:
mode:
authorJeffrey Wilcke <geffobscura@gmail.com>2015-08-30 16:19:10 +0800
committerJeffrey Wilcke <geffobscura@gmail.com>2015-10-04 07:13:54 +0800
commit361082ec4b942aea7c01fcb1be1782cb68b6fe3a (patch)
treed3ed9276cc61d314a6de14de1a61ea2c2d9a70b2 /core/state_transition.go
parentf7a71996fbbe9cea4445600ffa3c232a6cf42803 (diff)
downloadgo-tangerine-361082ec4b942aea7c01fcb1be1782cb68b6fe3a.tar
go-tangerine-361082ec4b942aea7c01fcb1be1782cb68b6fe3a.tar.gz
go-tangerine-361082ec4b942aea7c01fcb1be1782cb68b6fe3a.tar.bz2
go-tangerine-361082ec4b942aea7c01fcb1be1782cb68b6fe3a.tar.lz
go-tangerine-361082ec4b942aea7c01fcb1be1782cb68b6fe3a.tar.xz
go-tangerine-361082ec4b942aea7c01fcb1be1782cb68b6fe3a.tar.zst
go-tangerine-361082ec4b942aea7c01fcb1be1782cb68b6fe3a.zip
cmd/evm, core/vm, test: refactored VM and core
* Moved `vm.Transfer` to `core` package and changed execution to call `env.Transfer` instead of `core.Transfer` directly. * core/vm: byte code VM moved to jump table instead of switch * Moved `vm.Transfer` to `core` package and changed execution to call `env.Transfer` instead of `core.Transfer` directly. * Byte code VM now shares the same code as the JITVM * Renamed Context to Contract * Changed initialiser of state transition & unexported methods * Removed the Execution object and refactor `Call`, `CallCode` & `Create` in to their own functions instead of being methods. * Removed the hard dep on the state for the VM. The VM now depends on a Database interface returned by the environment. In the process the core now depends less on the statedb by usage of the env * Moved `Log` from package `core/state` to package `core/vm`.
Diffstat (limited to 'core/state_transition.go')
-rw-r--r--core/state_transition.go67
1 files changed, 36 insertions, 31 deletions
diff --git a/core/state_transition.go b/core/state_transition.go
index 6ff7fa1ff..e83019229 100644
--- a/core/state_transition.go
+++ b/core/state_transition.go
@@ -51,7 +51,7 @@ type StateTransition struct {
initialGas *big.Int
value *big.Int
data []byte
- state *state.StateDB
+ state vm.Database
env vm.Environment
}
@@ -95,11 +95,7 @@ func IntrinsicGas(data []byte) *big.Int {
}
func ApplyMessage(env vm.Environment, msg Message, gp GasPool) ([]byte, *big.Int, error) {
- return NewStateTransition(env, msg, gp).transitionState()
-}
-
-func NewStateTransition(env vm.Environment, msg Message, gp GasPool) *StateTransition {
- return &StateTransition{
+ var st = StateTransition{
gp: gp,
env: env,
msg: msg,
@@ -108,18 +104,22 @@ func NewStateTransition(env vm.Environment, msg Message, gp GasPool) *StateTrans
initialGas: new(big.Int),
value: msg.Value(),
data: msg.Data(),
- state: env.State(),
+ state: env.Db(),
}
+ return st.transitionDb()
}
-func (self *StateTransition) From() (*state.StateObject, error) {
+func (self *StateTransition) from() (vm.Account, error) {
f, err := self.msg.From()
if err != nil {
return nil, err
}
- return self.state.GetOrNewStateObject(f), nil
+ if !self.state.Exist(f) {
+ return self.state.CreateAccount(f), nil
+ }
+ return self.state.GetAccount(f), nil
}
-func (self *StateTransition) To() *state.StateObject {
+func (self *StateTransition) to() vm.Account {
if self.msg == nil {
return nil
}
@@ -127,10 +127,14 @@ func (self *StateTransition) To() *state.StateObject {
if to == nil {
return nil // contract creation
}
- return self.state.GetOrNewStateObject(*to)
+
+ if !self.state.Exist(*to) {
+ return self.state.CreateAccount(*to)
+ }
+ return self.state.GetAccount(*to)
}
-func (self *StateTransition) UseGas(amount *big.Int) error {
+func (self *StateTransition) useGas(amount *big.Int) error {
if self.gas.Cmp(amount) < 0 {
return vm.OutOfGasError
}
@@ -139,15 +143,15 @@ func (self *StateTransition) UseGas(amount *big.Int) error {
return nil
}
-func (self *StateTransition) AddGas(amount *big.Int) {
+func (self *StateTransition) addGas(amount *big.Int) {
self.gas.Add(self.gas, amount)
}
-func (self *StateTransition) BuyGas() error {
+func (self *StateTransition) buyGas() error {
mgas := self.msg.Gas()
mgval := new(big.Int).Mul(mgas, self.gasPrice)
- sender, err := self.From()
+ sender, err := self.from()
if err != nil {
return err
}
@@ -157,7 +161,7 @@ func (self *StateTransition) BuyGas() error {
if err = self.gp.SubGas(mgas, self.gasPrice); err != nil {
return err
}
- self.AddGas(mgas)
+ self.addGas(mgas)
self.initialGas.Set(mgas)
sender.SubBalance(mgval)
return nil
@@ -165,18 +169,19 @@ func (self *StateTransition) BuyGas() error {
func (self *StateTransition) preCheck() (err error) {
msg := self.msg
- sender, err := self.From()
+ sender, err := self.from()
if err != nil {
return err
}
// Make sure this transaction's nonce is correct
- if sender.Nonce() != msg.Nonce() {
- return NonceError(msg.Nonce(), sender.Nonce())
+ //if sender.Nonce() != msg.Nonce() {
+ if n := self.state.GetNonce(sender.Address()); n != msg.Nonce() {
+ return NonceError(msg.Nonce(), n)
}
// Pre-pay gas / Buy gas of the coinbase account
- if err = self.BuyGas(); err != nil {
+ if err = self.buyGas(); err != nil {
if state.IsGasLimitErr(err) {
return err
}
@@ -186,28 +191,28 @@ func (self *StateTransition) preCheck() (err error) {
return nil
}
-func (self *StateTransition) transitionState() (ret []byte, usedGas *big.Int, err error) {
+func (self *StateTransition) transitionDb() (ret []byte, usedGas *big.Int, err error) {
if err = self.preCheck(); err != nil {
return
}
msg := self.msg
- sender, _ := self.From() // err checked in preCheck
+ sender, _ := self.from() // err checked in preCheck
// Pay intrinsic gas
- if err = self.UseGas(IntrinsicGas(self.data)); err != nil {
+ if err = self.useGas(IntrinsicGas(self.data)); err != nil {
return nil, nil, InvalidTxError(err)
}
vmenv := self.env
- var ref vm.ContextRef
+ var addr common.Address
if MessageCreatesContract(msg) {
- ret, err, ref = vmenv.Create(sender, self.data, self.gas, self.gasPrice, self.value)
+ ret, addr, err = vmenv.Create(sender, self.data, self.gas, self.gasPrice, self.value)
if err == nil {
dataGas := big.NewInt(int64(len(ret)))
dataGas.Mul(dataGas, params.CreateDataGas)
- if err := self.UseGas(dataGas); err == nil {
- ref.SetCode(ret)
+ if err := self.useGas(dataGas); err == nil {
+ self.state.SetCode(addr, ret)
} else {
ret = nil // does not affect consensus but useful for StateTests validations
glog.V(logger.Core).Infoln("Insufficient gas for creating code. Require", dataGas, "and have", self.gas)
@@ -216,8 +221,8 @@ func (self *StateTransition) transitionState() (ret []byte, usedGas *big.Int, er
glog.V(logger.Core).Infoln("VM create err:", err)
} else {
// Increment the nonce for the next transaction
- self.state.SetNonce(sender.Address(), sender.Nonce()+1)
- ret, err = vmenv.Call(sender, self.To().Address(), self.data, self.gas, self.gasPrice, self.value)
+ self.state.SetNonce(sender.Address(), self.state.GetNonce(sender.Address())+1)
+ ret, err = vmenv.Call(sender, self.to().Address(), self.data, self.gas, self.gasPrice, self.value)
glog.V(logger.Core).Infoln("VM call err:", err)
}
@@ -241,13 +246,13 @@ func (self *StateTransition) transitionState() (ret []byte, usedGas *big.Int, er
}
func (self *StateTransition) refundGas() {
- sender, _ := self.From() // err already checked
+ sender, _ := self.from() // err already checked
// Return remaining gas
remaining := new(big.Int).Mul(self.gas, self.gasPrice)
sender.AddBalance(remaining)
uhalf := remaining.Div(self.gasUsed(), common.Big2)
- refund := common.BigMin(uhalf, self.state.Refunds())
+ refund := common.BigMin(uhalf, self.state.GetRefund())
self.gas.Add(self.gas, refund)
self.state.AddBalance(sender.Address(), refund.Mul(refund, self.gasPrice))